Megapatch, changes which states are available, how they're used, and how they're set. Also modifies the scheduling s...

Original commit message from CVS:
Megapatch, changes which states are available, how they're used, and how
they're set.  Also modifies the scheduling system, breaking pulled
buffers.  Check mail archives for more details.
This commit is contained in:
Erik Walthinsen 2000-07-17 17:14:15 +00:00
parent 5effd6fe5d
commit b6d31c1c72
30 changed files with 657 additions and 450 deletions

View file

@ -1,4 +1,4 @@
SUBDIRS = gst plugins test editor tools docs libs
SUBDIRS = gst libs plugins test editor tools docs tests
bin_SCRIPTS = gstreamer-config

View file

@ -61,7 +61,7 @@ for dir in `find * -name autogen.sh -print | grep -v '^autogen.sh$' | \
popd > /dev/null
done
./configure --enable-maintainer-mode "$@"
./configure --enable-maintainer-mode --enable-debug "$@"
echo
echo "Now type 'make' to compile $package."

View file

@ -51,7 +51,7 @@ AM_PATH_GLIB(1.2.0,,
glib gmodule gthread)
dnl Put the glib flags into $LIBS and $CFLAGS since we always use them
LIBS="$LIBS $GLIB_LIBS"
CFLAGS="$FLAGS $GLIB_CFLAGS"
CFLAGS="$CFLAGS $GLIB_CFLAGS"
dnl Check for libxml
AC_PATH_PROG(XML_CONFIG, xml-config, no)
@ -306,7 +306,7 @@ AM_CONDITIONAL(HAVE_LIBMMX, test "x$USE_LIBMMX" = "xyes")
AM_CONDITIONAL(HAVE_ATOMIC_H, test "x$USE_ATOMIC_H" = "xyes")
AM_CONDITIONAL(HAVE_XAUDIO, test "x$HAVE_XAUDIO" = "xyes")
AM_CONDITIONAL(HAVE_CSSAUTH, test "x$HAVE_CSSAUTH" = "xyes")
AM_CONDITIONAL(HAVE_GTK_DOC, $HAVE_GTK_DOC)
AM_CONDITIONAL(HAVE_GTK_DOC, test "x$HAVE_GTK_DOC" = "xyes")
dnl FIXME: having to AC_SUBST these is messy. Not sure if CPPFLAGS and LDFLAGS

View file

@ -1,8 +1,8 @@
SUBDIRS =
if HAVE_GTK_DOC
SUBDIRS += gst
SUBDIRS += gst manual
endif
DIST_SUBDIRS = gst
DIST_SUBDIRS = gst manual
EXTRA_DIST = random slides

View file

@ -136,25 +136,6 @@ struct GstBin {
cothread_context *threadcontext;
};
</STRUCT>
<STRUCT>
<NAME>GstBinClass</NAME>
struct GstBinClass {
GstElementClass parent_class;
void (*object_added) (GstObject *object,GstObject *child);
/* change the state of elements of the given type */
gboolean (*change_state_type) (GstBin *bin,
GstElementState state,
GtkType type);
/* create a plan for the execution of the bin */
void (*create_plan) (GstBin *bin);
/* run a full iteration of operation */
void (*iterate) (GstBin *bin);
};
</STRUCT>
<FUNCTION>
<NAME>gst_bin_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -359,64 +340,6 @@ GstBuffer *buffer
<RETURNS>void </RETURNS>
GstBuffer *buffer,GstMeta *meta
</FUNCTION>
<TYPEDEF>
<NAME>GstClockTime</NAME>
typedef guint64 GstClockTime;
</TYPEDEF>
<TYPEDEF>
<NAME>GstClockTimeDiff</NAME>
typedef gint64 GstClockTimeDiff;
</TYPEDEF>
<MACRO>
<NAME>GST_CLOCK_DIFF</NAME>
#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
</MACRO>
<STRUCT>
<NAME>GstClock</NAME>
</STRUCT>
<STRUCT>
<NAME>GstClock</NAME>
struct GstClock {
gchar *name;
GstClockTime start_time;
GstClockTime current_time;
GstClockTimeDiff adjust;
gboolean locking;
GList *sinkobjects;
GMutex *sinkmutex;
GMutex *lock;
};
</STRUCT>
<FUNCTION>
<NAME>gst_clock_new</NAME>
<RETURNS>GstClock *</RETURNS>
gchar *name
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_get_system</NAME>
<RETURNS>GstClock *</RETURNS>
void
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_register</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstObject *obj
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_set</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstClockTime time
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_reset</NAME>
<RETURNS>void </RETURNS>
GstClock *clock
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_wait</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstClockTime time, GstObject *obj
</FUNCTION>
<MACRO>
<NAME>GST_TYPE_CONNECTION</NAME>
#define GST_TYPE_CONNECTION \
@ -454,15 +377,6 @@ struct GstConnection {
GstElement element;
};
</STRUCT>
<STRUCT>
<NAME>GstConnectionClass</NAME>
struct GstConnectionClass {
GstElementClass parent_class;
/* push function */
void (*push) (GstConnection *connection);
};
</STRUCT>
<FUNCTION>
<NAME>gst_connection_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -504,14 +418,16 @@ typedef enum {
<NAME>GST_STATE_SET</NAME>
#define GST_STATE_SET(obj,flag) \
G_STMT_START{ (GST_STATE (obj) |= (flag)); \
gst_info("set '%s' state %d\n",gst_element_get_name(obj),flag); \
gst_info("set '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
_gst_print_statename(flag)); \
}G_STMT_END
</MACRO>
<MACRO>
<NAME>GST_STATE_UNSET</NAME>
#define GST_STATE_UNSET(obj,flag) \
G_STMT_START{ (GST_STATE (obj) &= ~(flag)); \
gst_info("unset '%s' state %d\n",gst_element_get_name(obj),flag); \
gst_info("unset '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
_gst_print_statename(flag)); \
}G_STMT_END
</MACRO>
<MACRO>
@ -539,6 +455,16 @@ gst_info("unset '%s' state %d\n",gst_element_get_name(obj),flag); \
#define GST_IS_ELEMENT_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
</MACRO>
<ENUM>
<NAME>GstElementFlags</NAME>
typedef enum {
GST_ELEMENT_MULTI_OUT = (1 << 16),
} GstElementFlags;
</ENUM>
<MACRO>
<NAME>GST_ELEMENT_IS_MULTI_OUT</NAME>
#define GST_ELEMENT_IS_MULTI_OUT(obj) ((GST_FLAGS(obj) & GST_ELEMENT_MULTI_OUT)
</MACRO>
<STRUCT>
<NAME>GstElement</NAME>
</STRUCT>
@ -575,32 +501,6 @@ struct GstElement {
};
</STRUCT>
<STRUCT>
<NAME>GstElementClass</NAME>
struct GstElementClass {
GstObjectClass parent_class;
/* the elementfactory that created us */
GstElementFactory *elementfactory;
/* signal callbacks */
void (*state_change) (GstElement *element,GstElementState state);
void (*new_pad) (GstElement *element,GstPad *pad);
void (*new_ghost_pad) (GstElement *element,GstPad *pad);
void (*error) (GstElement *element,gchar *error);
/* events */
gboolean (*start) (GstElement *element,GstElementState state);
gboolean (*stop) (GstElement *element);
/* change the element state */
gboolean (*change_state) (GstElement *element,GstElementState state);
/* create or read XML representation of self */
xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent);
void (*restore_thyself)(GstElement *element,xmlNodePtr *self);
};
</STRUCT>
<STRUCT>
<NAME>GstElementDetails</NAME>
struct GstElementDetails {
gchar *longname; /* long, english name */
@ -776,12 +676,6 @@ struct GstFilter {
GstElement element;
};
</STRUCT>
<STRUCT>
<NAME>GstFilterClass</NAME>
struct GstFilterClass {
GstElementClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_filter_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -926,17 +820,6 @@ struct GstObject {
GstObject *parent;
};
</STRUCT>
<STRUCT>
<NAME>GstObjectClass</NAME>
struct GstObjectClass {
GtkObjectClass parent_class;
/* signals */
void (*parent_set) (GstObject *object,GstObject *parent);
/* functions go here */
};
</STRUCT>
<MACRO>
<NAME>GST_FLAGS</NAME>
#define GST_FLAGS(obj) GTK_OBJECT_FLAGS(obj)
@ -1028,13 +911,11 @@ GstObject *object
</MACRO>
<MACRO>
<NAME>GST_PAD_CONNECTED</NAME>
#define GST_PAD_CONNECTED(pad) \
((pad)->peer != NULL)
#define GST_PAD_CONNECTED(pad) ((pad)->peer != NULL)
</MACRO>
<MACRO>
<NAME>GST_PAD_CAN_PULL</NAME>
#define GST_PAD_CAN_PULL(pad) \
((pad)->pull != NULL)
#define GST_PAD_CAN_PULL(pad) ((pad)->pullfunc != NULL)
</MACRO>
<STRUCT>
<NAME>GstPad</NAME>
@ -1049,7 +930,7 @@ GstPad *pad,GstBuffer *buf
</USER_FUNCTION>
<USER_FUNCTION>
<NAME>GstPadPullFunction</NAME>
<RETURNS>GstBuffer *</RETURNS>
<RETURNS>void </RETURNS>
GstPad *pad
</USER_FUNCTION>
<USER_FUNCTION>
@ -1079,19 +960,14 @@ struct GstPad {
GstBuffer *bufpen;
GstPadChainFunction chain;
GstPadPullFunction pull;
GstPadChainFunction chainfunc;
GstPadPullFunction pullfunc;
GstPadPushFunction pushfunc;
GstObject *parent;
GList *ghostparents;
};
</STRUCT>
<STRUCT>
<NAME>GstPadClass</NAME>
struct GstPadClass {
GstObjectClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_pad_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1233,12 +1109,6 @@ struct GstPipeline {
GstBin bin;
};
</STRUCT>
<STRUCT>
<NAME>GstPipelineClass</NAME>
struct GstPipelineClass {
GstBinClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_pipeline_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1368,12 +1238,6 @@ struct GstSink {
GstElement element;
};
</STRUCT>
<STRUCT>
<NAME>GstSinkClass</NAME>
struct GstSinkClass {
GstElementClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_sink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1438,19 +1302,6 @@ struct GstSrc {
gint32 flags;
};
</STRUCT>
<STRUCT>
<NAME>GstSrcClass</NAME>
struct GstSrcClass {
GstElementClass parent_class;
/* subclass functions */
void (*push) (GstSrc *src);
void (*push_region) (GstSrc *src,gulong offset,gulong size);
/* signals */
void (*eos) (GstSrc *src);
};
</STRUCT>
<MACRO>
<NAME>GST_SRC_SET_FLAGS</NAME>
#define GST_SRC_SET_FLAGS(src,flag) \
@ -1523,12 +1374,6 @@ struct GstTee {
GSList *srcpads;
};
</STRUCT>
<STRUCT>
<NAME>GstTeeClass</NAME>
struct GstTeeClass {
GstFilterClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_tee_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1593,20 +1438,11 @@ typedef enum {
struct GstThread {
GstBin bin;
GList *entries; /* used to determine iterate behavior */
gint numentries; /* number of above entry points */
pthread_t thread_id; /* id of the thread, if any */
GMutex *lock; /* thread lock/condititon pair... */
GCond *cond; /* used to control the thread */
};
</STRUCT>
<STRUCT>
<NAME>GstThreadClass</NAME>
struct GstThreadClass {
GstBinClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_thread_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1825,6 +1661,64 @@ GtkObject *object,guchar *argname
<RETURNS>xmlDocPtr </RETURNS>
GstElement *element
</FUNCTION>
<TYPEDEF>
<NAME>GstClockTime</NAME>
typedef guint64 GstClockTime;
</TYPEDEF>
<TYPEDEF>
<NAME>GstClockTimeDiff</NAME>
typedef gint64 GstClockTimeDiff;
</TYPEDEF>
<MACRO>
<NAME>GST_CLOCK_DIFF</NAME>
#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
</MACRO>
<STRUCT>
<NAME>GstClock</NAME>
</STRUCT>
<STRUCT>
<NAME>GstClock</NAME>
struct GstClock {
gchar *name;
GstClockTime start_time;
GstClockTime current_time;
GstClockTimeDiff adjust;
gboolean locking;
GList *sinkobjects;
GMutex *sinkmutex;
GMutex *lock;
};
</STRUCT>
<FUNCTION>
<NAME>gst_clock_new</NAME>
<RETURNS>GstClock *</RETURNS>
gchar *name
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_get_system</NAME>
<RETURNS>GstClock *</RETURNS>
void
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_register</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstObject *obj
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_set</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstClockTime time
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_reset</NAME>
<RETURNS>void </RETURNS>
GstClock *clock
</FUNCTION>
<FUNCTION>
<NAME>gst_clock_wait</NAME>
<RETURNS>void </RETURNS>
GstClock *clock, GstClockTime time, GstObject *obj
</FUNCTION>
<MACRO>
<NAME>GST_TYPE_ASYNCDISKSRC</NAME>
#define GST_TYPE_ASYNCDISKSRC \
@ -1885,12 +1779,6 @@ struct GstAsyncDiskSrc {
gulong seq; /* buffer sequence number */
};
</STRUCT>
<STRUCT>
<NAME>GstAsyncDiskSrcClass</NAME>
struct GstAsyncDiskSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_asyncdisksrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -1944,15 +1832,6 @@ struct GstAudioSink {
gint frequency;
};
</STRUCT>
<STRUCT>
<NAME>GstAudioSinkClass</NAME>
struct GstAudioSinkClass {
GstSinkClass parent_class;
/* signals */
void (*handoff) (GstElement *element,GstPad *pad);
};
</STRUCT>
<FUNCTION>
<NAME>gst_audiosink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2014,12 +1893,6 @@ struct GstAudioSrc {
MetaAudioRaw *meta;
};
</STRUCT>
<STRUCT>
<NAME>GstAudioSrcClass</NAME>
struct GstAudioSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_audiosrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2080,12 +1953,6 @@ struct GstDiskSrc {
gulong seq; /* buffer sequence number */
};
</STRUCT>
<STRUCT>
<NAME>GstDiskSrcClass</NAME>
struct GstDiskSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_disksrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2137,15 +2004,6 @@ struct GstEsdSink {
gint frequency;
};
</STRUCT>
<STRUCT>
<NAME>GstEsdSinkClass</NAME>
struct GstEsdSinkClass {
GstFilterClass parent_class;
/* signals */
void (*handoff) (GstElement *element,GstPad *pad);
};
</STRUCT>
<FUNCTION>
<NAME>gst_esdsink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2190,12 +2048,6 @@ struct GstFakeSink {
GstPad *sinkpad;
};
</STRUCT>
<STRUCT>
<NAME>GstFakeSinkClass</NAME>
struct GstFakeSinkClass {
GstSinkClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_fakesink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2240,12 +2092,6 @@ struct GstFakeSrc {
GstPad *srcpad;
};
</STRUCT>
<STRUCT>
<NAME>GstFakeSrcClass</NAME>
struct GstFakeSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_fakesrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2292,12 +2138,6 @@ struct GstFdSink {
int fd;
};
</STRUCT>
<STRUCT>
<NAME>GstFdSinkClass</NAME>
struct GstFdSinkClass {
GstSinkClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_fdsink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2350,12 +2190,6 @@ struct GstFdSrc {
gulong seq; /* buffer sequence number */
};
</STRUCT>
<STRUCT>
<NAME>GstFdSrcClass</NAME>
struct GstFdSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_fdsrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2407,12 +2241,6 @@ struct GstHttpSrc {
gulong bytes_per_read; /* bytes per read */
};
</STRUCT>
<STRUCT>
<NAME>GstHttpSrcClass</NAME>
struct GstHttpSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_httpsrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2460,12 +2288,6 @@ struct GstIdentity {
gint control;
};
</STRUCT>
<STRUCT>
<NAME>GstIdentityClass</NAME>
struct GstIdentityClass {
GstFilterClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_identity_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2526,12 +2348,6 @@ struct GstQueue {
GCond *fullcond;
};
</STRUCT>
<STRUCT>
<NAME>GstQueueClass</NAME>
struct GstQueueClass {
GstConnectionClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_queue_get_type</NAME>
<RETURNS>GtkType </RETURNS>
@ -2585,18 +2401,15 @@ struct GstSineSrc {
gint channels;
gint frequency;
/* state */
double mTheta;
gulong seq;
MetaAudioRaw meta;
gboolean sentmeta;
};
</STRUCT>
<STRUCT>
<NAME>GstSineSrcClass</NAME>
struct GstSineSrcClass {
GstSrcClass parent_class;
};
</STRUCT>
<FUNCTION>
<NAME>gst_sinesrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>

View file

@ -58,6 +58,9 @@ libgstinclude_HEADERS = \
cothreads.h
CFLAGS += -O2 -Wall
#if USE_DEBUG
CFLAGS += -g
#endif
libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS)
libgst_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE)

View file

@ -45,13 +45,13 @@ struct _elements_entry {
};
struct _elements_entry _elements[] = {
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
{ "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details },
{ "identity", gst_identity_get_type, &gst_identity_details },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details },
#if HAVE_LIBGHTTP

View file

@ -86,8 +86,8 @@ static void gst_fakesink_init(GstFakeSink *fakesink) {
gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad);
gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain);
// we're already complete, since we don't have any args...
gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE);
// we're ready right away, since we don't have any args...
// gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_READY);
}
/**
@ -120,8 +120,8 @@ void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) {
g_return_if_fail(buf != NULL);
fakesink = GST_FAKESINK(pad->parent);
// g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n",
// buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink)));
// g_print("gst_fakesink_chain: got buffer in '%s'\n",
// gst_element_get_name(GST_ELEMENT(fakesink)));
g_print("<");
gst_buffer_unref(buf);
}

View file

@ -87,8 +87,8 @@ static void gst_fakesrc_init(GstFakeSrc *fakesrc) {
fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad);
// we're already complete, since we don't have any args...
gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE);
// we're ready right away, since we don't have any args...
// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
}
/**

View file

@ -31,13 +31,11 @@ GstElementDetails gst_bin_details = {
void gst_bin_real_destroy(GtkObject *object);
static gboolean gst_bin_change_state(GstElement *element,
GstElementState state);
static GstElementStateReturn gst_bin_change_state(GstElement *element);
static GstElementStateReturn gst_bin_change_state_norecurse(GstBin *bin);
static gboolean gst_bin_change_state_type(GstBin *bin,
GstElementState state,
GtkType type);
static gboolean gst_bin_change_state_norecurse(GstElement *element,
GstElementState state);
static void gst_bin_create_plan_func(GstBin *bin);
static void gst_bin_iterate_func(GstBin *bin);
@ -143,28 +141,38 @@ void gst_bin_add(GstBin *bin,GstElement *element) {
g_return_if_fail(element != NULL);
g_return_if_fail(GST_IS_ELEMENT(element));
// must be NULL or PAUSED state in order to modify bin
g_return_if_fail((GST_STATE(bin) == GST_STATE_NULL) ||
(GST_STATE(bin) == GST_STATE_PAUSED));
bin->children = g_list_append(bin->children,element);
bin->numchildren++;
gst_object_set_parent(GST_OBJECT(element),GST_OBJECT(bin));
#ifdef OLDSTATE
/* FIXME: this isn't right, the bin should be complete whether or not
the children are, I think. */
// if (GST_STATE_IS_SET(element,GST_STATE_COMPLETE)) {
if (!GST_STATE_IS_SET(bin,GST_STATE_COMPLETE)) {
g_print("GstBin: adding complete element - \n");
gst_bin_change_state_norecurse(GST_ELEMENT(bin),GST_STATE_COMPLETE);
g_print("GstBin: adding complete element - ");
gst_bin_change_state_norecurse(GST_ELEMENT(bin));
}
// } else {
// g_print("GstBin: adding element - ");
// gst_bin_change_state_norecurse(GST_ELEMENT(bin),~GST_STATE_COMPLETE);
// }
#else
/* we know we have at least one child, we just added one... */
// if (GST_STATE(element) < GST_STATE_READY)
// gst_bin_change_state_norecurse(bin,GST_STATE_READY);
#endif
gtk_signal_emit(GTK_OBJECT(bin),gst_bin_signals[OBJECT_ADDED],element);
}
/**
* gst_bin_remove:
* @bin: #Gstbin to remove element from
* @bin: #GstBin to remove element from
* @element: #GstElement to remove
*
* Remove the element from its associated bin, unparenting as well.
@ -176,57 +184,74 @@ void gst_bin_remove(GstBin *bin,GstElement *element) {
g_return_if_fail(GST_IS_ELEMENT(element));
g_return_if_fail(bin->children != NULL);
// must be NULL or PAUSED state in order to modify bin
g_return_if_fail((GST_STATE(bin) == GST_STATE_NULL) ||
(GST_STATE(bin) == GST_STATE_PAUSED));
gst_object_unparent(GST_OBJECT(element));
bin->children = g_list_remove(bin->children,element);
bin->numchildren--;
/* if we're down to zero children, force state to NULL */
if (bin->numchildren == 0)
gst_element_set_state(GST_ELEMENT(bin),GST_STATE_NULL);
}
static gboolean gst_bin_change_state(GstElement *element,
GstElementState state) {
static GstElementStateReturn gst_bin_change_state(GstElement *element) {
GstBin *bin;
GList *children;
GstElement *child;
// g_print("gst_bin_change_state(\"%s\",%d);\n",
// gst_object_get_name(GST_OBJECT(bin)),state);
g_return_val_if_fail(GST_IS_BIN(element), FALSE);
g_return_val_if_fail(GST_IS_BIN(element), GST_STATE_FAILURE);
bin = GST_BIN(element);
g_return_val_if_fail(bin->numchildren != 0, FALSE);
g_print("gst_bin_change_state(\"%s\"): currently %d(%s), %d(%s) pending\n",
gst_element_get_name(element),GST_STATE(element),
_gst_print_statename(GST_STATE(element)),GST_STATE_PENDING(element),
_gst_print_statename(GST_STATE_PENDING(element)));
// g_return_val_if_fail(bin->numchildren != 0, GST_STATE_FAILURE);
// g_print("-->\n");
children = bin->children;
while (children) {
child = GST_ELEMENT(children->data);
//g_print("gst_bin_change_state setting state on \"%s\"\n",
// gst_element_get_name(GST_ELEMENT(child)));
if (!gst_element_set_state(child,state)) {
g_print("GstBin: child %p failed to set state 0x%08x\n",child,state);
return FALSE;
g_print("gst_bin_change_state: setting state on '%s'\n",
gst_element_get_name(child));
switch (gst_element_set_state(child,GST_STATE_PENDING(element))) {
case GST_STATE_FAILURE:
GST_STATE_PENDING(element) = GST_STATE_NONE_PENDING;
g_print("child '%s' failed to go to state %d(%s)\n",gst_element_get_name(child),
GST_STATE_PENDING(element),_gst_print_statename(GST_STATE_PENDING(element)));
return GST_STATE_FAILURE;
break;
case GST_STATE_ASYNC:
g_print("child '%s' is changing state asynchronously\n",gst_element_get_name(child));
break;
}
// g_print("\n");
children = g_list_next(children);
}
// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin)));
if (GST_ELEMENT_CLASS(parent_class)->change_state)
return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
return TRUE;
// if (GST_STATE_PENDING(element),
return gst_bin_change_state_norecurse(bin);
}
static gboolean gst_bin_change_state_norecurse(GstElement *element,
GstElementState state) {
GstBin *bin;
g_return_val_if_fail(GST_IS_BIN(element), FALSE);
bin = GST_BIN(element);
g_return_val_if_fail(bin->numchildren != 0, FALSE);
static GstElementStateReturn gst_bin_change_state_norecurse(GstBin *bin) {
/*
if ((state == GST_STATE_READY) && (GST_STATE(bin) < GST_STATE_READY)) {
// gst_bin_create_plan(
}
*/
if (GST_ELEMENT_CLASS(parent_class)->change_state)
return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
return TRUE;
return GST_ELEMENT_CLASS(parent_class)->change_state(bin);
else
return GST_STATE_FAILURE;
}
static gboolean gst_bin_change_state_type(GstBin *bin,
@ -371,6 +396,7 @@ void gst_bin_iterate(GstBin *bin) {
oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass);
g_print("gst_bin_iterate()\n");
if (oclass->iterate)
(oclass->iterate)(bin);
}
@ -384,6 +410,7 @@ void gst_bin_create_plan(GstBin *bin) {
(oclass->create_plan)(bin);
}
#ifdef OLD_STUFF
static void gst_bin_create_plan_func(GstBin *bin) {
GList *elements;
GstElement *element;
@ -400,7 +427,8 @@ static void gst_bin_create_plan_func(GstBin *bin) {
while (elements) {
element = GST_ELEMENT(elements->data);
// have to use cothreads if any elements use loop functions
// have to use cothreads if any elements use loop functions, or if any
// of them have nontrivial chain functions
if (element->loopfunc != NULL) {
if (bin->threadcontext == NULL) {
g_print("GstBin: initializing cothread context\n");
@ -414,14 +442,14 @@ static void gst_bin_create_plan_func(GstBin *bin) {
}
}
/* we need to find all the entry points into the bin */
// we need to find all the entry points into the bin
if (GST_IS_SRC(element)) {
g_print("GstBin: element '%s' is a source entry point for the bin\n",
gst_element_get_name(GST_ELEMENT(element)));
bin->entries = g_list_prepend(bin->entries,element);
bin->numentries++;
} else {
/* go through the list of pads to see if there's a Connection */
// go through the list of pads to see if there's a Connection
pads = gst_element_get_pad_list(element);
while (pads) {
pad = GST_PAD(pads->data);
@ -449,31 +477,187 @@ for internal element '%s'\n",
}
elements = g_list_next(elements);
}
g_print("GstBin: have %d entries into bin\n",bin->numentries);
g_print("have %d entries into bin\n",bin->numentries);
}
#endif
static int gst_bin_loopfunc_wrapper(int argc,char *argv[]) {
GstElement *element = GST_ELEMENT(argv);
GList *pads;
GstPad *pad;
GstBuffer *buf;
// g_print("** gst_bin_loopfunc_wrapper(%d,\"%s\")\n",
// argc,gst_element_get_name(element));
if (element->loopfunc != NULL) {
// g_print("** gst_bin_loopfunc_wrapper(): element has loop function, calling it\n");
while (1) {
(element->loopfunc)(element);
}
} else {
// g_print("** gst_bin_loopfunc_wrapper(): element is chain-based, calling in infinite loop\n");
if (GST_IS_SRC(element)) {
while (1) {
// g_print("** gst_bin_loopfunc_wrapper(): calling push function of source\n");
gst_src_push(GST_SRC(element));
}
} else {
while (1) {
pads = element->pads;
while (pads) {
pad = GST_PAD(pads->data);
if (pad->direction == GST_PAD_SINK) {
// g_print("** gst_bin_loopfunc_wrapper(): pulling a buffer\n");
buf = gst_pad_pull(pad);
// g_print("** gst_bin_loopfunc_wrapper(): calling chain function\n");
(pad->chainfunc)(pad,buf);
}
pads = g_list_next(pads);
}
}
}
}
}
static void gst_bin_pullfunc_wrapper(GstPad *pad) {
// g_print("** in gst_bin_pullfunc_wrapper()============================= %s\n",
// gst_element_get_name(GST_ELEMENT(pad->parent)));
cothread_switch(GST_ELEMENT(pad->parent)->threadstate);
}
static void gst_bin_pushfunc_wrapper(GstPad *pad) {
// g_print("** in gst_bin_pushfunc_wrapper()============================= %s\n",
// gst_element_get_name(GST_ELEMENT(pad->parent)));
cothread_switch(GST_ELEMENT(pad->parent)->threadstate);
}
static void gst_bin_create_plan_func(GstBin *bin) {
GList *elements;
GstElement *element;
int sink_pads;
GList *pads;
GstPad *pad, *peer;
GstElement *outside;
g_print("creating plan for bin\n");
// first loop through all children to see if we need cothreads
// we break immediately when we find we need to, why keep searching?
elements = bin->children;
while (elements) {
element = GST_ELEMENT(elements->data);
// if it's a loop-based element, use cothreads
if (element->loopfunc != NULL) {
bin->need_cothreads = TRUE;
break;
}
// if it's a complex element, use cothreads
if (GST_ELEMENT_IS_MULTI_IN(element)) {
bin->need_cothreads = TRUE;
break;
}
// if it has more than one input pad, use cothreads
sink_pads = 0;
pads = gst_element_get_pad_list(element);
while (pads) {
pad = GST_PAD(pads->data);
if (pad->direction == GST_PAD_SINK)
sink_pads++;
pads = g_list_next(pads);
}
if (sink_pads > 1) {
bin->need_cothreads = TRUE;
break;
}
elements = g_list_next(elements);
}
if (bin->need_cothreads) {
g_print("BIN: need cothreads\n");
// first create thread context
if (bin->threadcontext == NULL) {
bin->threadcontext = cothread_init();
g_print("initialized cothread context\n");
}
// walk through all the children
elements = bin->children;
while (elements) {
element = GST_ELEMENT(elements->data);
// start by creating thread state for the element
if (element->threadstate == NULL) {
element->threadstate = cothread_create(bin->threadcontext);
cothread_setfunc(element->threadstate,gst_bin_loopfunc_wrapper,
0,(char **)element);
}
pads = gst_element_get_pad_list(element);
while (pads) {
pad = GST_PAD(pads->data);
g_print("setting push&pull handlers for %s:%s\n",
gst_element_get_name(element),gst_pad_get_name(pad));
// if (pad->direction == GST_PAD_SRC)
pad->pushfunc = gst_bin_pushfunc_wrapper;
// else
pad->pullfunc = gst_bin_pullfunc_wrapper;
pads = g_list_next(pads);
}
elements = g_list_next(elements);
}
} else {
g_print("BIN: don't need cothreads, looking for entry points\n");
// clear previous plan state
g_list_free(bin->entries);
bin->numentries = 0;
// we have to find which elements will drive an iteration
elements = bin->children;
while (elements) {
element = GST_ELEMENT(elements->data);
if (GST_IS_SRC(element)) {
g_print("adding '%s' as entry point\n",gst_element_get_name(element));
bin->entries = g_list_prepend(bin->entries,element);
bin->numentries++;
}
elements = g_list_next(elements);
}
}
}
void gst_bin_iterate_func(GstBin *bin) {
GList *entries;
GstElement *entry;
g_print("gst_bin_iterate_func()\n");
g_return_if_fail(bin != NULL);
g_return_if_fail(GST_IS_BIN(bin));
// g_return_if_fail(GST_FLAG_IS_SET(thread,GST_STATE_RUNNING));
g_return_if_fail(GST_STATE(bin) == GST_STATE_PLAYING);
g_return_if_fail(bin->numentries > 0);
entries = bin->entries;
g_print("GstBin: iterating\n");
while (entries) {
entry = GST_ELEMENT(entries->data);
if (GST_IS_SRC(entry))
gst_src_push(GST_SRC(entry));
else if (GST_IS_CONNECTION(entry))
gst_connection_push(GST_CONNECTION(entry));
else
g_assert_not_reached();
entries = g_list_next(entries);
if (bin->need_cothreads) {
// all we really have to do is switch to the first child
// FIXME this should be lots more intelligent about where to start
// g_print("** in gst_bin_iterate_func()==================================%s\n",
// gst_element_get_name(GST_ELEMENT(bin->children->data)));
cothread_switch(GST_ELEMENT(bin->children->data)->threadstate);
} else {
entries = bin->entries;
while (entries) {
entry = GST_ELEMENT(entries->data);
if (GST_IS_SRC(entry))
gst_src_push(GST_SRC(entry));
else if (GST_IS_CONNECTION(entry))
gst_connection_push(GST_CONNECTION(entry));
else
g_assert_not_reached();
entries = g_list_next(entries);
}
}
// g_print(",");
}

View file

@ -52,9 +52,12 @@ typedef struct _GstBinClass GstBinClass;
struct _GstBin {
GstElement element;
// our children
gint numchildren;
GList *children;
// iteration state
gboolean need_cothreads;
GList *entries;
gint numentries;

View file

@ -105,7 +105,6 @@ void gst_clock_wait(GstClock *clock, GstClockTime time, GstObject *obj) {
struct timeval tfnow;
GstClockTime now;
GstClockTimeDiff diff;
GList *elements;
//DEBUG("gst_clock: requesting clock object 0x%p %08llu %08llu\n", obj, time, clock->current_time);

View file

@ -39,6 +39,9 @@ static void gst_element_class_init(GstElementClass *klass);
static void gst_element_init(GstElement *element);
static void gst_element_real_destroy(GtkObject *object);
GstElementStateReturn gst_element_change_state(GstElement *element);
static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
@ -92,15 +95,14 @@ static void gst_element_class_init(GstElementClass *klass) {
gtk_object_class_add_signals(gtkobject_class,gst_element_signals,LAST_SIGNAL);
klass->start = NULL;
klass->stop = NULL;
klass->change_state = gst_element_change_state;
gtkobject_class->destroy = gst_element_real_destroy;
}
static void gst_element_init(GstElement *element) {
element->state = 0;
element->current_state = GST_STATE_NULL;
element->pending_state = -1;
element->numpads = 0;
element->pads = NULL;
element->loopfunc = NULL;
@ -282,37 +284,31 @@ void gst_element_error(GstElement *element,gchar *error) {
*
* Returns: whether or not the state was successfully set.
*/
gboolean gst_element_set_state(GstElement *element,GstElementState state) {
gint gst_element_set_state(GstElement *element,GstElementState state) {
GstElementClass *oclass;
gboolean stateset = FALSE;
GstElementStateReturn return_val = GST_STATE_SUCCESS;
// g_print("gst_element_set_state(\"%s\",%08lx)\n",
// element->name,state);
g_return_val_if_fail(element != NULL, FALSE);
g_return_val_if_fail(GST_IS_ELEMENT(element), FALSE);
g_return_val_if_fail(element != NULL, GST_STATE_FAILURE);
g_return_val_if_fail(GST_IS_ELEMENT(element), GST_STATE_FAILURE);
// first we set the pending state variable
// FIXME should probably check to see that we don't already have one
GST_STATE_PENDING(element) = state;
// now we call the state change function so it can set the state
oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
if (oclass->change_state)
stateset = (oclass->change_state)(element,state);
return_val = (oclass->change_state)(element);
/* if a state *set* failed, unset it immediately */
/*
if (!(state & GST_STATE_MAX) && !stateset) {
g_print("set state failed miserably, forcing unset\n");
if (oclass->change_state)
stateset = (oclass->change_state)(element,~state);
return FALSE;
}*/
return stateset;
return return_val;
}
/**
* gst_element_change_state:
* @element: element to change state of
* @state: new element state
*
* Changes the state of the element, but more importantly fires off a signal
* indicating the new state. You can clear state by simply prefixing the
@ -321,14 +317,14 @@ gboolean gst_element_set_state(GstElement *element,GstElementState state) {
*
* Returns: whether or not the state change was successfully set.
*/
gboolean gst_element_change_state(GstElement *element,
GstElementState state) {
g_return_val_if_fail(element != NULL, FALSE);
g_return_val_if_fail(GST_IS_ELEMENT(element), FALSE);
GstElementStateReturn gst_element_change_state(GstElement *element) {
g_return_val_if_fail(element != NULL, GST_STATE_FAILURE);
g_return_val_if_fail(GST_IS_ELEMENT(element), GST_STATE_FAILURE);
// g_print("gst_element_change_state(\"%s\",%d)\n",
// element->name,state);
#ifdef OLDSTATE
/* deal with the inverted state */
//g_print("changing element state, was %08lx\n",GST_STATE(element));
if (state & GST_STATE_MAX)
@ -336,8 +332,12 @@ gboolean gst_element_change_state(GstElement *element,
else
GST_STATE_SET(element,state);
// g_print(", is now %08lx\n",GST_STATE(element));
#else
GST_STATE(element) = GST_STATE_PENDING(element);
GST_STATE_PENDING(element) = GST_STATE_NONE_PENDING;
#endif
gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[STATE_CHANGE],
state);
GST_STATE(element));
return TRUE;
}
@ -541,6 +541,7 @@ GstElement *gst_element_get_manager(GstElement *element) {
int gst_element_loopfunc_wrapper(int argc,char **argv) {
GstElement *element = GST_ELEMENT(argv);
element->loopfunc(element);
return 0;
}
/**

View file

@ -35,6 +35,7 @@ extern "C" {
#endif /* __cplusplus */
#ifdef OLDSTATES
typedef enum {
GST_STATE_COMPLETE = (1 << 0),
GST_STATE_RUNNING = (1 << 1),
@ -47,17 +48,55 @@ typedef enum {
GST_STATE_MAX = (1 << 15),
} GstElementState;
typedef enum {
GST_STATE_FAILURE = 0,
GST_STATE_SUCCESS = 1,
GST_STATE_ASYNC = 2,
};
#else
typedef enum {
GST_STATE_NONE_PENDING = -1,
GST_STATE_NULL = 0,
GST_STATE_READY = 1,
GST_STATE_PLAYING = 2,
GST_STATE_PAUSED = 3,
} GstElementState;
#define GST_STATE(obj) (GST_ELEMENT(obj)->state)
typedef enum {
GST_STATE_FAILURE = 0,
GST_STATE_SUCCESS = 1,
GST_STATE_ASYNC = 2,
} GstElementStateReturn;
#endif
static inline char *_gst_print_statename(int state) {
switch (state) {
case -1: return "none pending";break;
case 0: return "null";break;
case 1: return "ready";break;
case 2: return "playing";break;
case 3: return "paused";break;
default: return "";
}
return "";
}
#define GST_STATE(obj) (GST_ELEMENT(obj)->current_state)
#define GST_STATE_PENDING(obj) (GST_ELEMENT(obj)->pending_state)
#ifdef OLDSTATE
#define GST_STATE_IS_SET(obj,flag) (GST_STATE (obj) & (flag))
#define GST_STATE_SET(obj,flag) \
G_STMT_START{ (GST_STATE (obj) |= (flag)); \
gst_info("GstElement: set '%s' state %d\n",gst_element_get_name(obj),flag); \
gst_info("GstElement: set '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
_gst_print_statename(flag)); \
}G_STMT_END
#define GST_STATE_UNSET(obj,flag) \
G_STMT_START{ (GST_STATE (obj) &= ~(flag)); \
gst_info("GstElement: unset '%s' state %d\n",gst_element_get_name(obj),flag); \
gst_info("GstElement: unset '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
_gst_print_statename(flag)); \
}G_STMT_END
#endif
#define GST_TYPE_ELEMENT \
@ -71,6 +110,13 @@ gst_info("GstElement: unset '%s' state %d\n",gst_element_get_name(obj),flag); \
#define GST_IS_ELEMENT_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
typedef enum {
GST_ELEMENT_MULTI_IN = (1 << 16),
} GstElementFlags;
#define GST_ELEMENT_IS_MULTI_IN(obj) (GST_FLAGS(obj) & GST_ELEMENT_MULTI_IN)
typedef struct _GstElement GstElement;
typedef struct _GstElementClass GstElementClass;
typedef struct _GstElementDetails GstElementDetails;
@ -83,7 +129,8 @@ struct _GstElement {
gchar *name;
guint16 state;
guint8 current_state;
guint8 pending_state;
GstElementLoopFunction loopfunc;
cothread_state *threadstate;
@ -107,11 +154,11 @@ struct _GstElementClass {
void (*error) (GstElement *element,gchar *error);
/* events */
gboolean (*start) (GstElement *element,GstElementState state);
gboolean (*stop) (GstElement *element);
// gboolean (*start) (GstElement *element,GstElementState state);
// gboolean (*stop) (GstElement *element);
/* change the element state */
gboolean (*change_state) (GstElement *element,GstElementState state);
GstElementStateReturn (*change_state) (GstElement *element);
/* create or read XML representation of self */
xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent);
@ -156,14 +203,10 @@ void gst_element_connect(GstElement *src,gchar *srcpadname,
GstElement *dest,gchar *destpadname);
/* called by the app to set the state of the element */
gboolean gst_element_set_state(GstElement *element,GstElementState state);
gint gst_element_set_state(GstElement *element,GstElementState state);
void gst_element_error(GstElement *element,gchar *error);
/* callback to actually set the state */
gboolean gst_element_change_state(GstElement *element,
GstElementState state);
#define gst_element_destroy(element) gst_object_destroy(GST_OBJECT(element))
/* XML write and read */

View file

@ -80,9 +80,10 @@ static void gst_pad_init(GstPad *pad) {
pad->type = 0;
pad->direction = GST_PAD_UNKNOWN;
pad->peer = NULL;
pad->chain = NULL;
pad->pull = NULL;
pad->qos = NULL;
pad->chainfunc = NULL;
pad->pullfunc = NULL;
pad->pushfunc = NULL;
pad->qosfunc = NULL;
pad->parent = NULL;
pad->ghostparents = NULL;
}
@ -158,35 +159,60 @@ gchar *gst_pad_get_name(GstPad *pad) {
void gst_pad_set_pull_function(GstPad *pad,GstPadPullFunction pull) {
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
pad->pull = pull;
fprintf(stderr, "pad setting pull function\n");
pad->pullfunc = pull;
}
void gst_pad_set_chain_function(GstPad *pad,GstPadChainFunction chain) {
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
pad->chain = chain;
pad->chainfunc = chain;
}
void gst_pad_set_qos_function(GstPad *pad,GstPadQoSFunction qos) {
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
pad->qos = qos;
pad->qosfunc = qos;
}
/* gst_pad_push is handed the src pad and the buffer to push */
void gst_pad_push(GstPad *pad,GstBuffer *buffer) {
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
g_return_if_fail(GST_PAD_CONNECTED(pad));
// g_return_if_fail(GST_PAD_CONNECTED(pad));
g_return_if_fail(buffer != NULL);
gst_trace_add_entry(NULL,0,buffer,"push buffer");
// FIXME we should probably make some noise here...
if (!GST_PAD_CONNECTED(pad)) return;
// g_return_if_fail(pad->pushfunc != NULL);
// first check to see if there's a push handler
if (pad->pushfunc != NULL) {
// g_print("-- gst_pad_push(): putting buffer in pen and calling push handler\n");
// put the buffer in peer's holding pen
pad->peer->bufpen = buffer;
// now inform the handler that the peer pad has something
(pad->pushfunc)(pad->peer);
// otherwise we assume we're chaining directly
} else if (pad->chainfunc != NULL) {
(pad->chainfunc)(pad->peer,buffer);
// else we squawk
} else {
// g_print("-- gst_pad_push(): houston, we have a problem, no way of talking to peer\n");
}
#ifdef OLD_STUFF
// if the chain function exists for the pad, call it directly
if (pad->chain)
(pad->chain)(pad->peer,buffer);
// else we're likely going to have to coroutine it
// else we're likely going to have to cothread it
else {
pad->peer->bufpen = buffer;
g_print("GstPad: would switch to a coroutine here...\n");
@ -195,22 +221,51 @@ void gst_pad_push(GstPad *pad,GstBuffer *buffer) {
if (GST_ELEMENT(pad->peer->parent)->threadstate != NULL)
cothread_switch(GST_ELEMENT(pad->peer->parent)->threadstate);
}
#endif
}
/* gst_pad_pull() is given the sink pad */
GstBuffer *gst_pad_pull(GstPad *pad) {
GstBuffer *buf;
GstElement *peerparent;
cothread_state *state;
// GstElement *peerparent;
// cothread_state *state;
g_return_val_if_fail(pad != NULL, NULL);
g_return_val_if_fail(GST_IS_PAD(pad), NULL);
// g_print("-- gst_pad_pull(): attempting to pull buffer\n");
// g_return_val_if_fail(pad->pullfunc != NULL, NULL);
// if no buffer in pen and there's a pull handler, fire it
if (pad->bufpen == NULL) {
if (pad->pullfunc != NULL) {
// g_print("-- gst_pad_pull(): calling pull handler\n");
(pad->pullfunc)(pad->peer);
} else {
// g_print("-- gst_pad_pull(): no buffer in pen, and no handler to get one there!!!\n");
}
}
// if there's a buffer in the holding pen, use it
if (pad->bufpen != NULL) {
// g_print("-- gst_pad_pull(): buffer available, pulling\n");
buf = pad->bufpen;
pad->bufpen = NULL;
return buf;
// else we have a big problem...
} else {
// g_print("-- gst_pad_pull(): uh, nothing in pen and no handler\n");
return NULL;
}
#ifdef OLD_STUFF
// if the pull function exists for the pad, call it directly
if (pad->pull) {
return (pad->pull)(pad->peer);
// else we're likely going to have to coroutine it
// else we're likely going to have to cothread it
} else if (pad->bufpen == NULL) {
g_print("GstPad: no buffer available, will have to do something about it\n");
g_print("no buffer available, will have to do something about it\n");
peerparent = GST_ELEMENT(pad->peer->parent);
// if they're a cothread too, we can just switch to them
if (peerparent->threadstate != NULL) {
@ -227,19 +282,22 @@ GstBuffer *gst_pad_pull(GstPad *pad) {
pad->bufpen = NULL;
return buf;
}
return NULL;
#endif
return NULL;
}
void gst_pad_chain(GstPad *pad) {
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
g_return_if_fail(pad->peer != NULL);
g_return_if_fail(pad->chain != NULL);
g_return_if_fail(pad->chainfunc != NULL);
if (pad->bufpen)
(pad->chain)(pad,pad->bufpen);
if (pad->bufpen && pad->chainfunc)
(pad->chainfunc)(pad,pad->bufpen);
}
/**
* gst_pad_handle_qos:
* @element: element to change state of
@ -255,8 +313,8 @@ void gst_pad_handle_qos(GstPad *pad,
DEBUG("gst_pad_handle_qos(\"%s\",%08ld)\n", GST_ELEMENT(pad->parent)->name,qos_message);
if (pad->qos) {
(pad->qos)(pad,qos_message);
if (pad->qosfunc) {
(pad->qosfunc)(pad,qos_message);
}
else {
element = GST_ELEMENT(pad->peer->parent);
@ -292,9 +350,8 @@ void gst_pad_disconnect(GstPad *srcpad,GstPad *sinkpad) {
srcpad->peer = NULL;
sinkpad->peer = NULL;
srcpad->chain = NULL;
srcpad->pull = NULL;
srcpad->chainfunc = NULL;
srcpad->pullfunc = NULL;
}
void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad) {
@ -324,9 +381,9 @@ void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad) {
sinkpad->peer = srcpad;
/* now copy the chain pointer from sink to src */
srcpad->chain = sinkpad->chain;
srcpad->chainfunc = sinkpad->chainfunc;
/* and the pull function */
srcpad->pull = sinkpad->pull;
srcpad->pullfunc = sinkpad->pullfunc;
/* set the connected flag */
/* FIXME: set connected flag */

View file

@ -39,10 +39,8 @@ extern "C" {
#define GST_IS_PAD_CLASS(obj) (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PAD))
// quick test to see if the pad is connected
#define GST_PAD_CONNECTED(pad) \
((pad)->peer != NULL)
#define GST_PAD_CAN_PULL(pad) \
((pad)->pull != NULL)
#define GST_PAD_CONNECTED(pad) ((pad)->peer != NULL)
#define GST_PAD_CAN_PULL(pad) ((pad)->pullfunc != NULL)
typedef struct _GstPad GstPad;
typedef struct _GstPadClass GstPadClass;
@ -51,7 +49,7 @@ typedef struct _GstPadClass GstPadClass;
* pad is the sink pad (so the same chain function can be used for N pads)
* buf is the buffer being passed */
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
typedef GstBuffer *(*GstPadPullFunction) (GstPad *pad);
typedef void (*GstPadPullFunction) (GstPad *pad);
typedef void (*GstPadPushFunction) (GstPad *pad);
typedef void (*GstPadQoSFunction) (GstPad *pad, glong qos_message);
@ -76,9 +74,10 @@ struct _GstPad {
GstBuffer *bufpen;
GstPadChainFunction chain;
GstPadPullFunction pull;
GstPadQoSFunction qos;
GstPadChainFunction chainfunc;
GstPadPullFunction pullfunc;
GstPadPushFunction pushfunc;
GstPadQoSFunction qosfunc;
GstObject *parent;
GList *ghostparents;

View file

@ -44,8 +44,7 @@ enum {
static void gst_pipeline_class_init(GstPipelineClass *klass);
static void gst_pipeline_init(GstPipeline *pipeline);
static gboolean gst_pipeline_change_state(GstElement *element,
GstElementState state);
static GstElementStateReturn gst_pipeline_change_state(GstElement *element);
static void gst_pipeline_prepare(GstPipeline *pipeline);
@ -109,31 +108,33 @@ static void gst_pipeline_prepare(GstPipeline *pipeline) {
}
static gboolean gst_pipeline_change_state(GstElement *element,
GstElementState state) {
static GstElementStateReturn gst_pipeline_change_state(GstElement *element) {
GstPipeline *pipeline;
/*
g_return_val_if_fail(GST_IS_PIPELINE(element), FALSE);
pipeline = GST_PIPELINE(element);
switch (state) {
case GST_STATE_RUNNING:
/* we need to set up internal state */
g_print("GstPipeline: preparing pipeline \"%s\" for iterations:\n",
case GST_STATE_READY:
// we need to set up internal state
g_print("preparing pipeline \"%s\" for iterations:\n",
gst_element_get_name(GST_ELEMENT(element)));
gst_pipeline_prepare(pipeline);
break;
#if OLDSTATE
case ~GST_STATE_RUNNING:
/* tear down the internal state */
g_print("GstPipeline: tearing down pipelines's \"%s\" iteration state\n",
gst_element_get_name(GST_ELEMENT(element)));
// tear down the internal state
g_print("tearing down pipelines's iteration state\n");
break;
#endif
default:
break;
}
if (GST_ELEMENT_CLASS(parent_class)->change_state)
return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
*/
return TRUE;
}

View file

@ -47,8 +47,7 @@ static void gst_thread_init(GstThread *thread);
static void gst_thread_set_arg(GtkObject *object,GtkArg *arg,guint id);
static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id);
static gboolean gst_thread_change_state(GstElement *element,
GstElementState state);
static GstElementStateReturn gst_thread_change_state(GstElement *element);
static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent);
@ -104,8 +103,8 @@ gst_thread_class_init(GstThreadClass *klass) {
static void gst_thread_init(GstThread *thread) {
GST_FLAG_SET(thread,GST_THREAD_CREATE);
thread->entries = NULL;
thread->numentries = 0;
// thread->entries = NULL;
// thread->numentries = 0;
thread->lock = g_mutex_new();
thread->cond = g_cond_new();
@ -145,6 +144,7 @@ static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id) {
}
}
/**
* gst_thread_new:
* @name: the name of the thread
@ -162,6 +162,7 @@ GstElement *gst_thread_new(guchar *name) {
}
#ifdef OLD_STUFF
static void gst_thread_prepare(GstThread *thread) {
GList *elements;
GstElement *element;
@ -211,13 +212,14 @@ for internal element \"%s\"\n",
}
gst_info("gstthread: have %d entries into thread\n",thread->numentries);
}
#endif
static gboolean gst_thread_change_state(GstElement *element,
GstElementState state) {
static GstElementStateReturn gst_thread_change_state(GstElement *element) {
GstThread *thread;
gboolean stateset = TRUE;
/*
g_return_val_if_fail(GST_IS_THREAD(element), FALSE);
thread = GST_THREAD(element);
@ -225,18 +227,19 @@ static gboolean gst_thread_change_state(GstElement *element,
stateset = GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
switch (state) {
case GST_STATE_RUNNING:
case GST_STATE_READY:
if (!stateset) return FALSE;
/* we want to prepare our internal state for doing the iterations */
gst_info("gstthread: preparing thread \"%s\" for iterations:\n",
// we want to prepare our internal state for doing the iterations
gst_info("preparing thread \"%s\" for iterations:\n",
gst_element_get_name(GST_ELEMENT(element)));
gst_thread_prepare(thread);
if (thread->numentries == 0)
return FALSE;
/* set the state to idle */
// gst_thread_prepare(thread);
gst_bin_create_plan(GST_BIN(thread));
// if (thread->numentries == 0)
// return FALSE;
// set the state to idle
GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
/* create the thread if that's what we're supposed to do */
gst_info("gstthread: flags are 0x%08x\n",GST_FLAGS(thread));
// create the thread if that's what we're supposed to do
gst_info("flags are 0x%08x\n",GST_FLAGS(thread));
if (GST_FLAG_IS_SET(thread,GST_THREAD_CREATE)) {
gst_info("gstthread: starting thread \"%s\"\n",
gst_element_get_name(GST_ELEMENT(element)));
@ -248,17 +251,18 @@ static gboolean gst_thread_change_state(GstElement *element,
}
return TRUE;
break;
#if OLDSTATE
case ~GST_STATE_RUNNING:
/* stop, reap, and join the thread */
// stop, reap, and join the thread
GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
GST_FLAG_SET(thread,GST_THREAD_STATE_REAPING);
gst_thread_signal_thread(thread);
//pthread_join(thread->thread_id,0);
/* tear down the internal state */
gst_info("gstthread: tearing down thread's \"%s\" iteration state\n",
gst_element_get_name(GST_ELEMENT(element)));
/* FIXME do stuff */
pthread_join(thread->thread_id,0);
// tear down the internal state
gst_info("tearing down thread's iteration state\n");
// FIXME do stuff
break;
#endif
case GST_STATE_PLAYING:
if (!stateset) return FALSE;
gst_info("gstthread: starting thread \"%s\"\n",
@ -276,6 +280,7 @@ static gboolean gst_thread_change_state(GstElement *element,
default:
break;
}
*/
return stateset;
}
@ -295,7 +300,7 @@ void *gst_thread_main_loop(void *arg) {
while(!GST_FLAG_IS_SET(thread,GST_THREAD_STATE_REAPING)) {
if (GST_FLAG_IS_SET(thread,GST_THREAD_STATE_SPINNING))
gst_thread_iterate(thread);
gst_bin_iterate(GST_BIN(thread));
else {
g_mutex_lock(thread->lock);
g_cond_wait(thread->cond,thread->lock);
@ -311,6 +316,7 @@ void *gst_thread_main_loop(void *arg) {
return NULL;
}
#ifdef OLD_STUFF
/**
* gst_thread_iterate:
* @thread: the thread to iterate
@ -343,6 +349,7 @@ void gst_thread_iterate(GstThread *thread) {
DEBUG("gstthread: %s: thread iterate done\n", gst_element_get_name(GST_ELEMENT(thread)));
//g_print(",");
}
#endif
static void gst_thread_signal_thread(GstThread *thread) {
g_mutex_lock(thread->lock);

View file

@ -57,9 +57,6 @@ typedef struct _GstThreadClass GstThreadClass;
struct _GstThread {
GstBin bin;
GList *entries; /* used to determine iterate behavior */
gint numentries; /* number of above entry points */
pthread_t thread_id; /* id of the thread, if any */
GMutex *lock; /* thread lock/condititon pair... */
GCond *cond; /* used to control the thread */

View file

@ -45,13 +45,13 @@ struct _elements_entry {
};
struct _elements_entry _elements[] = {
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
{ "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details },
{ "identity", gst_identity_get_type, &gst_identity_details },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details },
#if HAVE_LIBGHTTP

View file

@ -86,8 +86,8 @@ static void gst_fakesink_init(GstFakeSink *fakesink) {
gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad);
gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain);
// we're already complete, since we don't have any args...
gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE);
// we're ready right away, since we don't have any args...
// gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_READY);
}
/**
@ -120,8 +120,8 @@ void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) {
g_return_if_fail(buf != NULL);
fakesink = GST_FAKESINK(pad->parent);
// g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n",
// buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink)));
// g_print("gst_fakesink_chain: got buffer in '%s'\n",
// gst_element_get_name(GST_ELEMENT(fakesink)));
g_print("<");
gst_buffer_unref(buf);
}

View file

@ -87,8 +87,8 @@ static void gst_fakesrc_init(GstFakeSrc *fakesrc) {
fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad);
// we're already complete, since we don't have any args...
gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE);
// we're ready right away, since we don't have any args...
// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
}
/**

View file

@ -3,15 +3,15 @@
extern gboolean _gst_plugin_spew;
int main(int argc,char *argv[]) {
GstPipeline *pipeline;
GstBin *bin;
GstElement *src, *sink;
GstPad *srcpad, *sinkpad;
// _gst_plugin_spew = TRUE;
gst_init(&argc,&argv);
pipeline = gst_pipeline_new("pipeline");
g_return_if_fail(pipeline != NULL);
bin = gst_bin_new("bin");
g_return_if_fail(bin != NULL);
g_print("--- creating src and sink elements\n");
src = gst_elementfactory_make("fakesrc","src");
@ -19,9 +19,9 @@ int main(int argc,char *argv[]) {
sink = gst_elementfactory_make("fakesink","sink");
g_return_if_fail(sink != NULL);
g_print("--- about to add the elements to the pipeline\n");
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(src));
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(sink));
g_print("--- about to add the elements to the bin\n");
gst_bin_add(bin,GST_ELEMENT(src));
gst_bin_add(bin,GST_ELEMENT(sink));
g_print("--- getting pads\n");
srcpad = gst_element_get_pad(src,"src");
@ -33,5 +33,10 @@ int main(int argc,char *argv[]) {
gst_pad_connect(srcpad,sinkpad);
g_print("--- setting up\n");
gst_pipeline_iterate(pipeline);
gst_element_set_state(GST_ELEMENT(bin),GST_STATE_READY);
g_print("--- creating plan\n");
gst_bin_create_plan(bin);
g_print("--- iterating\n");
gst_bin_iterate(bin);
}

12
tests/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs
*.xml
init
loadall
simplefake
states

7
tests/Makefile.am Normal file
View file

@ -0,0 +1,7 @@
noinst_PROGRAMS = init loadall simplefake states
LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_builddir)/gst/libgst.la
INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir)
EXTRA_DIST = README

2
tests/README Normal file
View file

@ -0,0 +1,2 @@
This directory contains various tests designed to verify GStreamer
behavior. If any of them exit with a non-zero value, something's wrong.

5
tests/init.c Normal file
View file

@ -0,0 +1,5 @@
#include <gst/gst.h>
int main(int argc,char *argv[]) {
gst_init(&argc,&argv);
}

6
tests/loadall.c Normal file
View file

@ -0,0 +1,6 @@
#include <gst/gst.h>
int main(int argc,char *argv[]) {
gst_init(&argc,&argv);
gst_plugin_load_all();
}

17
tests/simplefake.c Normal file
View file

@ -0,0 +1,17 @@
#include <gst/gst.h>
int main(int argc,char *argv[]) {
GstPipeline *pipeline;
GstElement *src,*sink;
gst_init(&argc,&argv);
pipeline = gst_pipeline_new("fakepipeline");
src = gst_elementfactory_make("fakesrc","fakesrc");
g_return_val_if_fail(1,src != NULL);
sink = gst_elementfactory_make("fakesink","fakesink");
g_return_val_if_fail(1,sink != NULL);
gst_bin_add(GST_BIN(pipeline),src);
gst_bin_add(GST_BIN(pipeline),sink);
}

46
tests/states.c Normal file
View file

@ -0,0 +1,46 @@
#include <gst/gst.h>
gboolean state_change(GstElement *element,GstElementState state) {
g_print("state_change: element '%s' state set to %d(%s)\n",
gst_element_get_name(element),state,_gst_print_statename(state));
g_print("state_change: element state is actually %d\n",GST_STATE(element));
}
int main(int argc,char *argv[]) {
GstElement *bin;
GstElement *src,*sink;
gst_init(&argc,&argv);
src = gst_elementfactory_make("fakesrc","src");
g_return_val_if_fail(1,src != NULL);
sink = gst_elementfactory_make("fakesink","sink");
g_return_val_if_fail(1,sink != NULL);
bin = gst_bin_new("bin");
g_return_val_if_fail(1,bin != NULL);
gtk_signal_connect(GTK_OBJECT(src),"state_change",
GTK_SIGNAL_FUNC(state_change),NULL);
gtk_signal_connect(GTK_OBJECT(sink),"state_change",
GTK_SIGNAL_FUNC(state_change),NULL);
gtk_signal_connect(GTK_OBJECT(bin),"state_change",
GTK_SIGNAL_FUNC(state_change),NULL);
g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(src),
GST_STATE(src),_gst_print_statename(GST_STATE(src)));
g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(sink),
GST_STATE(sink),_gst_print_statename(GST_STATE(sink)));
g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(bin),
GST_STATE(bin),_gst_print_statename(GST_STATE(bin)));
gst_bin_add(GST_BIN(bin),src);
gst_bin_add(GST_BIN(bin),sink);
gst_pad_connect(gst_element_get_pad(src,"src"),
gst_element_get_pad(sink,"sink"));
gst_bin_create_plan(bin);
gst_element_set_state(bin,GST_STATE_PLAYING);
gst_bin_iterate(bin);
}