CVS surgery + support to move base, check, and net out of gst and into libs/gst

Original commit message from CVS:
CVS surgery + support to move base, check, and net out of gst
and into libs/gst
This commit is contained in:
Thomas Vander Stichele 2005-11-29 19:12:30 +00:00
parent 65ce5ed080
commit a0c4c4812c
40 changed files with 91 additions and 8952 deletions

View file

@ -1,3 +1,46 @@
2005-11-29 Thomas Vander Stichele <thomas (at) apestaart (dot) org>
* check/Makefile.am:
* configure.ac:
* docs/gst/Makefile.am:
* gst/Makefile.am:
* gst/base/.cvsignore:
* gst/base/Makefile.am:
* gst/base/README:
* gst/base/gstadapter.c:
* gst/base/gstadapter.h:
* gst/base/gstbasesink.c:
* gst/base/gstbasesink.h:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c:
* gst/base/gstbasetransform.h:
* gst/base/gstcollectpads.c:
* gst/base/gstcollectpads.h:
* gst/base/gstpushsrc.c:
* gst/base/gstpushsrc.h:
* gst/base/gsttypefindhelper.c:
* gst/base/gsttypefindhelper.h:
* gst/check/Makefile.am:
* gst/check/gstcheck.c:
* gst/check/gstcheck.h:
* gst/net/Makefile.am:
* gst/net/gstnet.h:
* gst/net/gstnetclientclock.c:
* gst/net/gstnetclientclock.h:
* gst/net/gstnettimepacket.c:
* gst/net/gstnettimepacket.h:
* gst/net/gstnettimeprovider.c:
* gst/net/gstnettimeprovider.h:
* libs/gst/Makefile.am:
* libs/gst/base/Makefile.am:
* libs/gst/base/gstbasetransform.c:
* libs/gst/check/Makefile.am:
* plugins/elements/Makefile.am:
* po/POTFILES.in:
CVS surgery + support to move base, check, and net out of gst
and into libs/gst
2005-11-29 Andy Wingo <wingo@pobox.com>
* gst/gstevent.h (struct _GstEvent): Only one pointer of padding.

View file

@ -70,7 +70,7 @@ TESTS = $(check_PROGRAMS)
noinst_HEADERS = gst/capslist.h
AM_CFLAGS = $(GST_OBJ_CFLAGS) $(CHECK_CFLAGS)
LDADD = $(top_builddir)/gst/check/libgstcheck-@GST_MAJORMINOR@.la \
LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS) \
$(CHECK_LIBS)
@ -86,10 +86,10 @@ gst_libs_controller_LDADD = \
$(LDADD)
net_gstnetclientclock_LDADD = \
$(top_builddir)/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(LDADD)
net_gstnettimeprovider_LDADD = \
$(top_builddir)/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(LDADD)
# valgrind testing

View file

@ -473,14 +473,14 @@ Makefile
gst/Makefile
gst/gstconfig.h
gst/gstversion.h
gst/base/Makefile
gst/check/Makefile
gst/net/Makefile
gst/parse/Makefile
libs/Makefile
libs/gst/Makefile
libs/gst/base/Makefile
libs/gst/check/Makefile
libs/gst/controller/Makefile
libs/gst/dataprotocol/Makefile
libs/gst/net/Makefile
plugins/Makefile
plugins/indexers/Makefile
plugins/elements/Makefile

View file

@ -33,12 +33,6 @@ include $(srcdir)/../upload.mak
# The top-level SGML file. Change it if you want.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(top_srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/gst
DOC_BUILD_DIR=$(top_builddir)/gst
# Extra options to supply to gtkdoc-scan.
SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED"
@ -48,17 +42,22 @@ MKDB_OPTIONS=--sgml-mode --ignore-files=parse
# Extra options to supply to gtkdoc-fixref.
FIXXREF_OPTIONS=
# Used for dependencies.
HFILE_GLOB=$(DOC_SOURCE_DIR)/*.h
CFILE_GLOB=$(DOC_SOURCE_DIR)/*.c
# The files containing the source code. Relative to $(top_srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting functions and macros.
DOC_SOURCE_DIR = $(top_srcdir)/gst
DOC_BUILD_DIR = $(top_builddir)/gst
HFILE_GLOB=$(top_srcdir)/gst/*.h $(top_srcdir)/libs/gst/*/*.h
CFILE_GLOB=$(top_srcdir)/gst/*.c $(top_srcdir)/libs/gst/*/*.c
# Dependencies for the intermediate scanobj tool
#SCANOBJ_DEPS = $(top_builddir)/gst/elements/libgstelements.la \
# $(top_builddir)/gst/schedulers/libgstbasicomegascheduler.la
SCANOBJ_DEPS = \
$(top_builddir)/plugins/elements/libgstelements.la \
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(top_builddir)/gst/net/libgstnet-@GST_MAJORMINOR@.la
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la
# Header files to ignore when scanning. Use base file name, no paths
IGNORE_HFILES= \

View file

@ -1,11 +1,5 @@
lib_LTLIBRARIES = libgstreamer-@GST_MAJORMINOR@.la
if HAVE_CHECK
SUBDIRS_CHECK = check
else
SUBDIRS_CHECK =
endif
if GST_DISABLE_LOADSAVE
GST_LOADSAVE_SRC =
else
@ -52,24 +46,9 @@ else
GST_URI_SRC = gsturi.c
endif
if GST_DISABLE_NET
SUBDIRS_NET =
else
if HAVE_SYS_SOCKET_H
SUBDIRS_NET = net
else
SUBDIRS_NET =
endif
endif
SUBDIRS = $(SUBDIRS_PARSE)
SUBDIRS = \
$(SUBDIRS_PARSE) \
. \
base \
$(SUBDIRS_NET) \
$(SUBDIRS_CHECK)
DIST_SUBDIRS = base parse net check
DIST_SUBDIRS = parse
# make variables for all generated source and header files to make the
# distinction clear

1
gst/base/.gitignore vendored
View file

@ -1 +0,0 @@
*.gcno

View file

@ -1,29 +0,0 @@
lib_LTLIBRARIES = libgstbase-@GST_MAJORMINOR@.la
libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \
../libgstreamer-@GST_MAJORMINOR@.la
libgstbase_@GST_MAJORMINOR@_la_SOURCES = \
gstadapter.c \
gstbasesink.c \
gstbasesrc.c \
gstbasetransform.c \
gstcollectpads.c \
gstpushsrc.c \
gsttypefindhelper.c
libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS)
libgstbase_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
libgstbase_@GST_MAJORMINOR@includedir = \
$(includedir)/gstreamer-@GST_MAJORMINOR@/gst/base
libgstbase_@GST_MAJORMINOR@include_HEADERS = \
gstadapter.h \
gstbasesink.h \
gstbasesrc.h \
gstbasetransform.h \
gstcollectpads.h \
gstpushsrc.h \
gsttypefindhelper.h

View file

@ -1,6 +0,0 @@
Base classes
------------
GstBaseSink
FIXME: not much point making it operate in pull mode as a generic
base class I guess...

View file

@ -1,372 +0,0 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
*
* 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.
*/
/**
* SECTION:gstadapter
* @short_description: adapts incoming data on a sink pad into chunks of N bytes
*
* This class is for elements that receive buffers in an undesired size.
* While for example raw video contains one image per buffer, the same is not
* true for a lot of other formats, especially those that come directly from
* a file. So if you have undefined buffer sizes and require a specific size,
* this object is for you.
*
* The theory of operation is like this: All buffers received are put
* into the adapter using gst_adapter_push() and the data is then read back
* in chunks of the desired size using gst_adapter_peek(). After the data is
* processed, it is freed using gst_adapter_flush().
*
* For example, a sink pad's chain function that needs to pass data to a library
* in 512-byte chunks could be implemented like this:
* <programlisting>
* static GstFlowReturn
* sink_pad_chain (GstPad *pad, GstBuffer *buffer)
* {
* MyElement *this;
* GstAdapter *adapter;
* GstFlowReturn ret = GST_FLOW_OK;
*
* // will give the element an extra ref; remember to drop it
* this = MY_ELEMENT (gst_pad_get_parent (pad));
* adapter = this->adapter;
*
* // put buffer into adapter
* #gst_adapter_push (adapter, buffer);
* // while we can read out 512 bytes, process them
* while (#gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) {
* // use flowreturn as an error value
* ret = my_library_foo (#gst_adapter_peek (adapter, 512));
* #gst_adapter_flush (adapter, 512);
* }
*
* gst_object_unref (this);
* return ret;
* }
* </programlisting>
* For another example, a simple element inside GStreamer that uses GstAdapter
* is the libvisual element.
*
* An element using GstAdapter in its sink pad chain function should ensure that
* when the FLUSH_STOP event is received, that any queued data is cleared using
* gst_adapter_clear(). Data should also be cleared or processed on EOS and
* when changing state from #GST_STATE_PAUSED to #GST_STATE_READY.
*
* A last thing to note is that while GstAdapter is pretty optimized,
* merging buffers still might be an operation that requires a memcpy()
* operation, and this operation is not the fastest. Because of this, some
* functions like gst_adapter_available_fast() are provided to help speed up
* such cases should you want to.
*
* GstAdapter is not MT safe. All operations on an adapter must be serialized by
* the caller. This is not normally a problem, however, as the normal use case
* of GstAdapter is inside one pad's chain function, in which case access is
* serialized via the pad's stream lock.
*
* Last reviewed on 2005-11-08 (0.9.5).
*/
#include <string.h>
#include "gstadapter.h"
/* default size for the assembled data buffer */
#define DEFAULT_SIZE 16
GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
#define GST_CAT_DEFAULT gst_adapter_debug
#define _do_init(thing) \
GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,
_do_init);
static void gst_adapter_dispose (GObject * object);
static void gst_adapter_finalize (GObject * object);
static void
gst_adapter_base_init (gpointer g_class)
{
/* nop */
}
static void
gst_adapter_class_init (GstAdapterClass * klass)
{
GObjectClass *object = G_OBJECT_CLASS (klass);
object->dispose = gst_adapter_dispose;
object->finalize = gst_adapter_finalize;
}
static void
gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class)
{
adapter->assembled_data = g_malloc (DEFAULT_SIZE);
adapter->assembled_size = DEFAULT_SIZE;
}
static void
gst_adapter_dispose (GObject * object)
{
GstAdapter *adapter = GST_ADAPTER (object);
gst_adapter_clear (adapter);
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
static void
gst_adapter_finalize (GObject * object)
{
GstAdapter *adapter = GST_ADAPTER (object);
g_free (adapter->assembled_data);
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
/**
* gst_adapter_new:
*
* Creates a new #GstAdapter.
*
* Returns: a new #GstAdapter
*/
GstAdapter *
gst_adapter_new (void)
{
return g_object_new (GST_TYPE_ADAPTER, NULL);
}
/**
* gst_adapter_clear:
* @adapter: a #GstAdapter
*
* Removes all buffers from @adapter.
*/
void
gst_adapter_clear (GstAdapter * adapter)
{
g_return_if_fail (GST_IS_ADAPTER (adapter));
g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL);
g_slist_free (adapter->buflist);
adapter->buflist = NULL;
adapter->size = 0;
adapter->skip = 0;
adapter->assembled_len = 0;
}
/**
* gst_adapter_push:
* @adapter: a #GstAdapter
* @buf: a #GstBuffer to add to queue in the adapter
*
* Adds the data from @buf to the data stored inside @adapter and takes
* ownership of the buffer.
*/
void
gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
{
g_return_if_fail (GST_IS_ADAPTER (adapter));
g_return_if_fail (GST_IS_BUFFER (buf));
adapter->size += GST_BUFFER_SIZE (buf);
adapter->buflist = g_slist_append (adapter->buflist, buf);
}
/**
* gst_adapter_peek:
* @adapter: a #GstAdapter
* @size: the number of bytes to peek
*
* Gets the first @size bytes stored in the @adapter. The returned pointer is
* valid until the next function is called on the adapter.
*
* Note that setting the returned pointer as the data of a #GstBuffer is
* incorrect for general-purpose plugins. The reason is that if a downstream
* element stores the buffer so that it has access to it outside of the bounds
* of its chain function, the buffer will have an invalid data pointer after
* your element flushes the bytes. In that case you should use
* gst_adapter_take(), which returns a freshly-allocated buffer that you can set
* as #GstBuffer malloc_data.
*
* Returns #NULL if @size bytes are not available.
*
* Returns: a pointer to the first @size bytes of data, or NULL.
*/
const guint8 *
gst_adapter_peek (GstAdapter * adapter, guint size)
{
GstBuffer *cur;
GSList *cur_list;
guint copied;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
g_return_val_if_fail (size > 0, NULL);
/* we don't have enough data, return NULL */
if (size > adapter->size)
return NULL;
/* we have enough assembled data, return it */
if (adapter->assembled_len >= size)
return adapter->assembled_data;
/* our head buffer has enough data left, return it */
cur = adapter->buflist->data;
if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
return GST_BUFFER_DATA (cur) + adapter->skip;
if (adapter->assembled_size < size) {
adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
GST_DEBUG_OBJECT (adapter, "setting size of internal buffer to %u",
adapter->assembled_size);
adapter->assembled_data =
g_realloc (adapter->assembled_data, adapter->assembled_size);
}
adapter->assembled_len = size;
copied = GST_BUFFER_SIZE (cur) - adapter->skip;
memcpy (adapter->assembled_data, GST_BUFFER_DATA (cur) + adapter->skip,
copied);
cur_list = g_slist_next (adapter->buflist);
while (copied < size) {
g_assert (cur_list);
cur = cur_list->data;
cur_list = g_slist_next (cur_list);
memcpy (adapter->assembled_data + copied, GST_BUFFER_DATA (cur),
MIN (GST_BUFFER_SIZE (cur), size - copied));
copied = MIN (size, copied + GST_BUFFER_SIZE (cur));
}
return adapter->assembled_data;
}
/**
* gst_adapter_flush:
* @adapter: a #GstAdapter
* @flush: the number of bytes to flush
*
* Flushes the first @flush bytes in the @adapter. The caller must ensure that
* at least this many bytes are available.
*
* See also: gst_adapter_peek().
*/
void
gst_adapter_flush (GstAdapter * adapter, guint flush)
{
GstBuffer *cur;
g_return_if_fail (GST_IS_ADAPTER (adapter));
g_return_if_fail (flush >= 0);
g_return_if_fail (flush <= adapter->size);
GST_LOG_OBJECT (adapter, "flushing %u bytes", flush);
adapter->size -= flush;
adapter->assembled_len = 0;
while (flush > 0) {
cur = adapter->buflist->data;
if (GST_BUFFER_SIZE (cur) <= flush + adapter->skip) {
/* can skip whole buffer */
flush -= GST_BUFFER_SIZE (cur) - adapter->skip;
adapter->skip = 0;
adapter->buflist = g_slist_remove (adapter->buflist, cur);
gst_buffer_unref (cur);
} else {
adapter->skip += flush;
break;
}
}
}
/**
* gst_adapter_take:
* @adapter: a #GstAdapter
* @nbytes: the number of bytes to take
*
* Returns a freshly allocated buffer containing the first @nbytes bytes of the
* @adapter.
*
* Caller owns returned value.
*
* Returns: oven-fresh hot data, or #NULL if @nbytes bytes are not available
*/
guint8 *
gst_adapter_take (GstAdapter * adapter, guint nbytes)
{
const guint8 *cdata;
guint8 *data;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
g_return_val_if_fail (nbytes > 0, NULL);
GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
cdata = gst_adapter_peek (adapter, nbytes);
if (!cdata)
return NULL;
data = g_malloc (nbytes);
memcpy (data, cdata, nbytes);
gst_adapter_flush (adapter, nbytes);
return data;
}
/**
* gst_adapter_available:
* @adapter: a #GstAdapter
*
* Gets the maximum amount of bytes available, that is it returns the maximum
* value that can be supplied to gst_adapter_peek() without that function
* returning NULL.
*
* Returns: number of bytes available in @adapter
*/
guint
gst_adapter_available (GstAdapter * adapter)
{
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
return adapter->size;
}
/**
* gst_adapter_available_fast:
* @adapter: a #GstAdapter
*
* Gets the maximum number of bytes available without the need to do expensive
* operations (like copying the data into a temporary buffer).
*
* Returns: number of bytes available in @adapter without expensive operations
*/
guint
gst_adapter_available_fast (GstAdapter * adapter)
{
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
if (!adapter->buflist)
return 0;
if (adapter->assembled_len)
return adapter->assembled_len;
g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
}

View file

@ -1,86 +0,0 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
*
* 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 <gst/gst.h>
#ifndef __GST_ADAPTER_H__
#define __GST_ADAPTER_H__
G_BEGIN_DECLS
#define GST_TYPE_ADAPTER \
(gst_adapter_get_type())
#define GST_ADAPTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ADAPTER, GstAdapter))
#define GST_ADAPTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ADAPTER, GstAdapterClass))
#define GST_ADAPTER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ADAPTER, GstAdapterClass))
#define GST_IS_ADAPTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_ADAPTER))
#define GST_IS_ADAPTER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ADAPTER))
typedef struct _GstAdapter GstAdapter;
typedef struct _GstAdapterClass GstAdapterClass;
/**
* GstAdapter:
*
* The opaque #GstAdapter data structure.
*/
struct _GstAdapter {
GObject object;
/*< private >*/
GSList * buflist;
guint size;
guint skip;
/* we keep state of assembled pieces */
guint8 * assembled_data;
guint assembled_size;
guint assembled_len;
gpointer _gst_reserved[GST_PADDING];
};
struct _GstAdapterClass {
GObjectClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GstAdapter * gst_adapter_new (void);
void gst_adapter_clear (GstAdapter *adapter);
void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf);
const guint8 * gst_adapter_peek (GstAdapter *adapter, guint size);
void gst_adapter_flush (GstAdapter *adapter, guint flush);
guint8* gst_adapter_take (GstAdapter * adapter, guint nbytes);
guint gst_adapter_available (GstAdapter *adapter);
guint gst_adapter_available_fast (GstAdapter *adapter);
GType gst_adapter_get_type (void);
G_END_DECLS
#endif /* __GST_ADAPTER_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,130 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstbasesink.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_BASE_SINK_H__
#define __GST_BASE_SINK_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_BASE_SINK (gst_base_sink_get_type())
#define GST_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_SINK,GstBaseSink))
#define GST_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_SINK,GstBaseSinkClass))
#define GST_BASE_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_SINK, GstBaseSinkClass))
#define GST_IS_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_SINK))
#define GST_IS_BASE_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_SINK))
#define GST_BASE_SINK_CAST(obj) ((GstBaseSink *) (obj))
/**
* GST_BASE_SINK_PAD:
* @obj: base sink instance
*
* Gives the pointer to the #GstPad object of the element.
*/
#define GST_BASE_SINK_PAD(obj) (GST_BASE_SINK_CAST (obj)->sinkpad)
typedef struct _GstBaseSink GstBaseSink;
typedef struct _GstBaseSinkClass GstBaseSinkClass;
/**
* GstBaseSink:
*
* The opaque #GstBaseSink data structure.
*/
struct _GstBaseSink {
GstElement element;
/*< protected >*/
GstPad *sinkpad;
GstActivateMode pad_mode;
/*< protected >*/ /* with LOCK */
guint64 offset;
gboolean can_activate_pull;
gboolean can_activate_push;
/*< protected >*/ /* with PREROLL_LOCK */
GQueue *preroll_queue;
gint preroll_queue_max_len;
gint preroll_queued;
gint buffers_queued;
gint events_queued;
gboolean eos;
gboolean eos_queued;
gboolean need_preroll;
gboolean have_preroll;
gboolean playing_async;
/*< protected >*/ /* with STREAM_LOCK */
gboolean have_newsegment;
GstSegment segment;
/*< private >*/ /* with LOCK */
GstClockID clock_id;
GstClockTime end_time;
gboolean sync;
gboolean flushing;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstBaseSinkClass {
GstElementClass parent_class;
/* get caps from subclass */
GstCaps* (*get_caps) (GstBaseSink *sink);
/* notify subclass of new caps */
gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps);
/* allocate a new buffer with given caps */
GstFlowReturn (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
GstCaps *caps, GstBuffer **buf);
/* get the start and end times for syncing on this buffer */
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSink *sink);
gboolean (*stop) (GstBaseSink *sink);
/* unlock any pending access to the resource. subclasses should unlock
* any function ASAP. */
gboolean (*unlock) (GstBaseSink *sink);
/* notify subclass of event, preroll buffer or real buffer */
gboolean (*event) (GstBaseSink *sink, GstEvent *event);
GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_base_sink_get_type(void);
G_END_DECLS
#endif /* __GST_BASE_SINK_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,164 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* 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_BASE_SRC_H__
#define __GST_BASE_SRC_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_BASE_SRC (gst_base_src_get_type())
#define GST_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_SRC,GstBaseSrc))
#define GST_BASE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_SRC,GstBaseSrcClass))
#define GST_BASE_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_SRC, GstBaseSrcClass))
#define GST_IS_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_SRC))
#define GST_IS_BASE_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_SRC))
#define GST_BASE_SRC_CAST(obj) ((GstBaseSrc *)(obj))
/**
* GstBaseSrcFlags:
* @GST_BASE_SRC_STARTED: has source been started
* @GST_BASE_SRC_FLAG_LAST: offset to define more flags
*
* The #GstElement flags that a basesrc element may have.
*/
typedef enum {
GST_BASE_SRC_STARTED = (GST_ELEMENT_FLAG_LAST << 0),
/* padding */
GST_BASE_SRC_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2)
} GstBaseSrcFlags;
typedef struct _GstBaseSrc GstBaseSrc;
typedef struct _GstBaseSrcClass GstBaseSrcClass;
/**
* GST_BASE_SRC_PAD:
* @obj: base source instance
*
* Gives the pointer to the #GstPad object of the element.
*/
#define GST_BASE_SRC_PAD(obj) (GST_BASE_SRC_CAST (obj)->srcpad)
/**
* GstBaseSrc:
*
* The opaque #GstBaseSrc data structure.
*/
struct _GstBaseSrc {
GstElement element;
/*< protected >*/
GstPad *srcpad;
/* available to subclass implementations */
/* MT-protected (with LIVE_LOCK) */
GMutex *live_lock;
GCond *live_cond;
gboolean is_live;
gboolean live_running;
/* MT-protected (with LOCK) */
gint blocksize; /* size of buffers when operating push based */
gboolean can_activate_push; /* some scheduling properties */
GstActivateMode pad_mode;
gboolean seekable;
gboolean random_access;
GstClockID clock_id; /* for syncing */
GstClockTime end_time;
/* MT-protected (with STREAM_LOCK) */
GstSegment segment;
gboolean need_newsegment;
guint64 offset; /* current offset in the resource */
guint64 size; /* total size of the resource */
gint num_buffers;
gint num_buffers_left;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/**
* _GstBaseSrcClass:
* @create: ask the subclass to create a buffer with offset and size
* @start: start processing
*/
struct _GstBaseSrcClass {
GstElementClass parent_class;
/*< public >*/
/* virtual methods for subclasses */
/* get caps from subclass */
GstCaps* (*get_caps) (GstBaseSrc *src);
/* notify the subclass of new caps */
gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps);
/* decide on caps */
gboolean (*negotiate) (GstBaseSrc *src);
/* generate and send a newsegment */
gboolean (*newsegment) (GstBaseSrc *src);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSrc *src);
gboolean (*stop) (GstBaseSrc *src);
/* given a buffer, return start and stop time when it should be pushed
* out. The base class will sync on the clock using these times. */
void (*get_times) (GstBaseSrc *src, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
/* get the total size of the resource in bytes */
gboolean (*get_size) (GstBaseSrc *src, guint64 *size);
/* check if the resource is seekable */
gboolean (*is_seekable) (GstBaseSrc *src);
/* unlock any pending access to the resource. subclasses should unlock
* any function ASAP. */
gboolean (*unlock) (GstBaseSrc *src);
/* notify subclasses of an event */
gboolean (*event) (GstBaseSrc *src, GstEvent *event);
/* ask the subclass to create a buffer with offset and size */
GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size,
GstBuffer **buf);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_base_src_get_type (void);
void gst_base_src_set_live (GstBaseSrc *src, gboolean live);
gboolean gst_base_src_is_live (GstBaseSrc *src);
G_END_DECLS
#endif /* __GST_BASE_SRC_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,177 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2005 Wim Taymans <wim@fluendo.com>
*
* 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_BASE_TRANSFORM_H__
#define __GST_BASE_TRANSFORM_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_BASE_TRANSFORM (gst_base_transform_get_type())
#define GST_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransform))
#define GST_BASE_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass))
#define GST_BASE_TRANSFORM_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass))
#define GST_IS_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_TRANSFORM))
#define GST_IS_BASE_TRANSFORM_CLASS(obj)(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_TRANSFORM))
/**
* GST_BASE_TRANSFORM_SINK_NAME:
*
* the name of the templates for the sink pad
*/
#define GST_BASE_TRANSFORM_SINK_NAME "sink"
/**
* GST_BASE_TRANSFORM_SRC_NAME:
*
* the name of the templates for the source pad
*/
#define GST_BASE_TRANSFORM_SRC_NAME "src"
typedef struct _GstBaseTransform GstBaseTransform;
typedef struct _GstBaseTransformClass GstBaseTransformClass;
/**
* GstBaseTransform:
*
* The opaque #GstBaseTransform data structure.
*/
struct _GstBaseTransform {
GstElement element;
/*< protected >*/
/* source and sink pads */
GstPad *sinkpad;
GstPad *srcpad;
/* Set by sub-class */
gboolean passthrough;
gboolean always_in_place;
GstCaps *cache_caps1;
guint cache_caps1_size;
GstCaps *cache_caps2;
guint cache_caps2_size;
gboolean have_same_caps;
gboolean delay_configure;
gboolean pending_configure;
gboolean negotiated;
gboolean have_newsegment;
/* MT-protected (with STREAM_LOCK) */
GstSegment segment;
GMutex *transform_lock;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/**
* GstBaseTransformClass::transform_caps:
* @direction: the pad direction
* @caps: the caps
*
* This method should answer the question "given this pad, and given these
* caps, what caps would you allow on the other pad inside your element ?"
*/
struct _GstBaseTransformClass {
GstElementClass parent_class;
/*< public >*/
/* virtual methods for subclasses */
/* given the (non-)fixed simple caps on the pad in the given direction,
* what can I do on the other pad ? */
GstCaps* (*transform_caps) (GstBaseTransform *trans,
GstPadDirection direction,
GstCaps *caps);
/* given caps on one pad, how would you fixate caps on the other pad ? */
void (*fixate_caps) (GstBaseTransform *trans,
GstPadDirection direction, GstCaps *caps,
GstCaps *othercaps);
/* given the size of a buffer in the given direction with the given caps,
* calculate the byte size of an buffer on the other side with the given
* other caps; the default
* implementation uses get_size and keeps the number of units the same */
gboolean (*transform_size) (GstBaseTransform *trans,
GstPadDirection direction,
GstCaps *caps, guint size,
GstCaps *othercaps, guint *othersize);
/* get the byte size of one unit for a given caps.
* Always needs to be implemented if the transform is not in-place. */
gboolean (*get_unit_size) (GstBaseTransform *trans, GstCaps *caps,
guint *size);
/* notify the subclass of new caps */
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
GstCaps *outcaps);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseTransform *trans);
gboolean (*stop) (GstBaseTransform *trans);
gboolean (*event) (GstBaseTransform *trans, GstEvent *event);
/* transform one incoming buffer to one outgoing buffer.
* Always needs to be implemented unless always operating in-place.
* transform function is allowed to change size/timestamp/duration of
* the outgoing buffer. */
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
GstBuffer *outbuf);
/* transform a buffer inplace */
GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
/* FIXME: When adjusting the padding, more these to nicer places in the class */
/* Set by child classes to automatically do passthrough mode */
gboolean passthrough_on_same_caps;
/* Subclasses can override this to do their own allocation of output buffers.
* Elements that only do analysis can return a subbuffer or even just
* increment the reference to the input buffer (if in passthrough mode)
*/
GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
GstBuffer *input, gint size, GstCaps *caps, GstBuffer **buf);
/*< private >*/
gpointer _gst_reserved[GST_PADDING - 2];
};
GType gst_base_transform_get_type (void);
void gst_base_transform_set_passthrough (GstBaseTransform *trans,
gboolean passthrough);
gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
void gst_base_transform_set_in_place (GstBaseTransform *trans,
gboolean in_place);
gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
G_END_DECLS
#endif /* __GST_BASE_TRANSFORM_H__ */

View file

@ -1,701 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstcollectpads.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:gstcollectpads
* @short_description: manages a set of pads that operate in collect mode
* @see_also:
*
* Manages a set of pads that operate in collect mode. This means that control
* is given to the manager of this object when all pads have data.
* <itemizedlist>
* <listitem><para>
* Collectpads are created with gst_collect_pads_new(). A callback should then
* be installed with gst_collect_pads_set_function ().
* </para></listitem>
* <listitem><para>
* Pads are added to the collection with gst_collect_pads_add_pad()/
* gst_collect_pads_remove_pad(). The pad
* has to be a sinkpad. The chain function of the pad is
* overridden. The element_private of the pad is used to store
* private information.
* </para></listitem>
* <listitem><para>
* For each pad, data is queued in the chain function or by
* performing a pull_range.
* </para></listitem>
* <listitem><para>
* When data is queued on all pads, the callback function is called.
* </para></listitem>
* <listitem><para>
* Data can be dequeued from the pad with the gst_collect_pads_pop() method.
* One can peek at the data with the gst_collect_pads_peek() function.
* These functions will return NULL if the pad received an EOS event. When all
* pads return NULL from a gst_collect_pads_peek(), the element can emit an EOS
* event itself.
* </para></listitem>
* <listitem><para>
* Data can also be dequeued in byte units using the gst_collect_pads_available(),
* gst_collect_pads_read() and gst_collect_pads_flush() calls.
* </para></listitem>
* <listitem><para>
* Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in
* their state change functions to start and stop the processing of the collecpads.
* The gst_collect_pads_stop() call should be called before calling the parent
* element state change function in the PAUSED_TO_READY state change to ensure
* no pad is blocked and the element can finish streaming.
* </para></listitem>
* <listitem><para>
* gst_collect_pads_collect() and gst_collect_pads_collect_range() can be used by
* elements that start a #GstTask to drive the collect_pads.
* </para></listitem>
* </itemizedlist>
*/
#include "gstcollectpads.h"
GST_DEBUG_CATEGORY_STATIC (collect_pads_debug);
#define GST_CAT_DEFAULT collect_pads_debug
GST_BOILERPLATE (GstCollectPads, gst_collect_pads, GstObject, GST_TYPE_OBJECT)
static GstFlowReturn gst_collect_pads_chain (GstPad * pad,
GstBuffer * buffer);
static gboolean gst_collect_pads_event (GstPad * pad, GstEvent * event);
static void gst_collect_pads_finalize (GObject * object);
static void gst_collect_pads_init (GstCollectPads * pads,
GstCollectPadsClass * g_class);
static void gst_collect_pads_base_init (gpointer g_class)
{
GST_DEBUG_CATEGORY_INIT (collect_pads_debug, "collect_pads", 0,
"GstCollectPads");
}
static void
gst_collect_pads_class_init (GstCollectPadsClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collect_pads_finalize);
}
static void
gst_collect_pads_init (GstCollectPads * pads, GstCollectPadsClass * g_class)
{
pads->cond = g_cond_new ();
pads->data = NULL;
pads->cookie = 0;
pads->numpads = 0;
pads->queuedpads = 0;
pads->eospads = 0;
pads->started = FALSE;
}
static void
gst_collect_pads_finalize (GObject * object)
{
GstCollectPads *pads = GST_COLLECT_PADS (object);
gst_collect_pads_stop (pads);
g_cond_free (pads->cond);
/* FIXME, free data */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/**
* gst_collect_pads_new:
*
* Create a new instance of #GstCollectsPads.
*
* Returns: a new #GstCollectPads, or NULL in case of an error.
*
* MT safe.
*/
GstCollectPads *
gst_collect_pads_new (void)
{
GstCollectPads *newcoll;
newcoll = g_object_new (GST_TYPE_COLLECT_PADS, NULL);
return newcoll;
}
/**
* gst_collect_pads_set_function:
* @pads: the collectspads to use
* @func: the function to set
* @user_data: user data passed to the function
*
* Set the callback function and user data that will be called when
* all the pads added to the collection have buffers queued.
*
* MT safe.
*/
void
gst_collect_pads_set_function (GstCollectPads * pads,
GstCollectPadsFunction func, gpointer user_data)
{
g_return_if_fail (pads != NULL);
g_return_if_fail (GST_IS_COLLECT_PADS (pads));
GST_OBJECT_LOCK (pads);
pads->func = func;
pads->user_data = user_data;
GST_OBJECT_UNLOCK (pads);
}
/**
* gst_collect_pads_add_pad:
* @pads: the collectspads to use
* @pad: the pad to add
* @size: the size of the returned GstCollectData structure
*
* Add a pad to the collection of collect pads. The pad has to be
* a sinkpad.
*
* You specify a size for the returned #GstCollectData structure
* so that you can use it to store additional information.
*
* Returns: a new #GstCollectData to identify the new pad. Or NULL
* if wrong parameters are supplied.
*
* MT safe.
*/
GstCollectData *
gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
{
GstCollectData *data;
g_return_val_if_fail (pads != NULL, NULL);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL);
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL);
g_return_val_if_fail (size >= sizeof (GstCollectData), NULL);
data = g_malloc0 (size);
data->collect = pads;
data->pad = pad;
data->buffer = NULL;
gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_LOCK (pads);
pads->data = g_slist_append (pads->data, data);
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_chain));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_event));
gst_pad_set_element_private (pad, data);
pads->numpads++;
pads->cookie++;
GST_OBJECT_UNLOCK (pads);
return data;
}
static gint
find_pad (GstCollectData * data, GstPad * pad)
{
if (data->pad == pad)
return 0;
return 1;
}
/**
* gst_collect_pads_remove_pad:
* @pads: the collectspads to use
* @pad: the pad to remove
*
* Remove a pad from the collection of collect pads.
*
* Returns: TRUE if the pad could be removed.
*
* MT safe.
*/
gboolean
gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
{
GSList *list;
g_return_val_if_fail (pads != NULL, FALSE);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), FALSE);
g_return_val_if_fail (pad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
GST_OBJECT_LOCK (pads);
list = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
if (list) {
g_free (list->data);
pads->data = g_slist_delete_link (pads->data, list);
}
pads->numpads--;
pads->cookie++;
GST_OBJECT_UNLOCK (pads);
return list != NULL;
}
/**
* gst_collect_pads_is_active:
* @pads: the collectspads to use
* @pad: the pad to check
*
* Check if a pad is active.
*
* Returns: TRUE if the pad is active.
*
* MT safe.
*/
gboolean
gst_collect_pads_is_active (GstCollectPads * pads, GstPad * pad)
{
g_return_val_if_fail (pads != NULL, FALSE);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), FALSE);
g_return_val_if_fail (pad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_warning ("gst_collect_pads_is_active() is not implemented");
return FALSE;
}
/**
* gst_collect_pads_collect:
* @pads: the collectspads to use
*
* Collect data on all pads. This function is usually called
* from a GstTask function in an element. This function is
* currently not implemented.
*
* Returns: GstFlowReturn of the operation.
*
* MT safe.
*/
GstFlowReturn
gst_collect_pads_collect (GstCollectPads * pads)
{
g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR);
g_warning ("gst_collect_pads_collect() is not implemented");
return GST_FLOW_ERROR;
}
/**
* gst_collect_pads_collect_range:
* @pads: the collectspads to use
* @offset: the offset to collect
* @length: the length to collect
*
* Collect data with @offset and @length on all pads. This function
* is typically called in the getrange function of an element. This
* function is currently not implemented.
*
* Returns: GstFlowReturn of the operation.
*
* MT safe.
*/
GstFlowReturn
gst_collect_pads_collect_range (GstCollectPads * pads, guint64 offset,
guint length)
{
g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR);
g_warning ("gst_collect_pads_collect_range() is not implemented");
return GST_FLOW_ERROR;
}
/**
* gst_collect_pads_start:
* @pads: the collectspads to use
*
* Starts the processing of data in the collect_pads.
*
* MT safe.
*/
void
gst_collect_pads_start (GstCollectPads * pads)
{
g_return_if_fail (pads != NULL);
g_return_if_fail (GST_IS_COLLECT_PADS (pads));
GST_OBJECT_LOCK (pads);
pads->started = TRUE;
GST_OBJECT_UNLOCK (pads);
}
/**
* gst_collect_pads_stop:
* @pads: the collectspads to use
*
* Stops the processing of data in the collect_pads. this function
* will also unblock any blocking operations.
*
* MT safe.
*/
void
gst_collect_pads_stop (GstCollectPads * pads)
{
g_return_if_fail (pads != NULL);
g_return_if_fail (GST_IS_COLLECT_PADS (pads));
GST_OBJECT_LOCK (pads);
pads->started = FALSE;
GST_COLLECT_PADS_BROADCAST (pads);
GST_OBJECT_UNLOCK (pads);
}
/**
* gst_collect_pads_peek:
* @pads: the collectspads to peek
* @data: the data to use
*
* Peek at the buffer currently queued in @data. This function
* should be called with the @pads LOCK held, such as in the callback
* handler.
*
* Returns: The buffer in @data or NULL if no buffer is queued.
* should unref the buffer after usage.
*
* MT safe.
*/
GstBuffer *
gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data)
{
GstBuffer *result;
g_return_val_if_fail (pads != NULL, NULL);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL);
g_return_val_if_fail (data != NULL, NULL);
result = data->buffer;
if (result)
gst_buffer_ref (result);
GST_DEBUG ("Peeking at pad %s:%s: buffer=%p",
GST_DEBUG_PAD_NAME (data->pad), result);
return result;
}
/**
* gst_collect_pads_pop:
* @pads: the collectspads to pop
* @data: the data to use
*
* Pop the buffer currently queued in @data. This function
* should be called with the @pads LOCK held, such as in the callback
* handler.
*
* Returns: The buffer in @data or NULL if no buffer was queued.
* You should unref the buffer after usage.
*
* MT safe.
*/
GstBuffer *
gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data)
{
GstBuffer *result;
g_return_val_if_fail (pads != NULL, NULL);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL);
g_return_val_if_fail (data != NULL, NULL);
result = data->buffer;
if (result) {
gst_buffer_replace (&data->buffer, NULL);
data->pos = 0;
pads->queuedpads--;
}
GST_COLLECT_PADS_SIGNAL (pads);
GST_DEBUG ("Pop buffer on pad %s:%s: buffer=%p",
GST_DEBUG_PAD_NAME (data->pad), result);
return result;
}
/**
* gst_collect_pads_available:
* @pads: the collectspads to query
*
* Query how much bytes can be read from each queued buffer. This means
* that the result of this call is the maximum number of bytes that can
* be read from each of the pads.
*
* This function should be called with @pads LOCK held, such as
* in the callback.
*
* Returns: The maximum number of bytes queued on all pad. This function
* returns 0 if a pad has no queued buffer.
*
* MT safe.
*/
guint
gst_collect_pads_available (GstCollectPads * pads)
{
GSList *collected;
guint result = G_MAXUINT;
g_return_val_if_fail (pads != NULL, 0);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0);
for (collected = pads->data; collected; collected = g_slist_next (collected)) {
GstCollectData *pdata;
gint size;
pdata = (GstCollectData *) collected->data;
if (pdata->buffer == NULL)
goto not_filled;
size = GST_BUFFER_SIZE (pdata->buffer) - pdata->pos;
if (size < result)
result = size;
}
return result;
not_filled:
{
return 0;
}
}
/**
* gst_collect_pads_read:
* @pads: the collectspads to query
* @data: the data to use
* @bytes: a pointer to a byte array
* @size: the number of bytes to read
*
* Get a pointer in @bytes where @size bytes can be read from the
* given pad data.
*
* This function should be called with @pads LOCK held, such as
* in the callback.
*
* Returns: The number of bytes available for consumption in the
* memory pointed to by @bytes. This can be less than @size and
* is 0 if the pad is end-of-stream.
*
* MT safe.
*/
guint
gst_collect_pads_read (GstCollectPads * pads, GstCollectData * data,
guint8 ** bytes, guint size)
{
guint readsize;
g_return_val_if_fail (pads != NULL, 0);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0);
g_return_val_if_fail (data != NULL, 0);
g_return_val_if_fail (bytes != NULL, 0);
readsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
*bytes = GST_BUFFER_DATA (data->buffer) + data->pos;
return readsize;
}
/**
* gst_collect_pads_flush:
* @pads: the collectspads to query
* @data: the data to use
* @size: the number of bytes to flush
*
* Flush @size bytes from the pad @data.
*
* This function should be called with @pads LOCK held, such as
* in the callback.
*
* Returns: The number of bytes flushed This can be less than @size and
* is 0 if the pad was end-of-stream.
*
* MT safe.
*/
guint
gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,
guint size)
{
guint flushsize;
g_return_val_if_fail (pads != NULL, 0);
g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0);
g_return_val_if_fail (data != NULL, 0);
flushsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
data->pos += size;
if (data->pos >= GST_BUFFER_SIZE (data->buffer)) {
GstBuffer *buf;
buf = gst_collect_pads_pop (pads, data);
gst_buffer_unref (buf);
}
return flushsize;
}
static gboolean
gst_collect_pads_event (GstPad * pad, GstEvent * event)
{
GstCollectData *data;
GstCollectPads *pads;
/* some magic to get the managing collect_pads */
data = (GstCollectData *) gst_pad_get_element_private (pad);
if (data == NULL)
goto not_ours;
pads = data->collect;
GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
GST_DEBUG_PAD_NAME (data->pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
{
GstFlowReturn ret = GST_FLOW_OK;
GST_OBJECT_LOCK (pads);
pads->eospads++;
/* if all pads are EOS and we have a function, call it */
if ((pads->eospads == pads->numpads) && pads->func) {
ret = pads->func (pads, pads->user_data);
}
GST_OBJECT_UNLOCK (pads);
/* We eat this event */
gst_event_unref (event);
return TRUE;
break;
}
case GST_EVENT_NEWSEGMENT:
{
gint64 start, stop, time;
gdouble rate;
GstFormat format;
gboolean update;
gst_event_parse_new_segment (event, &update, &rate, &format,
&start, &stop, &time);
gst_segment_set_newsegment (&data->segment, update, rate, format,
start, stop, time);
goto beach;
}
default:
goto beach;
}
beach:
return gst_pad_event_default (pad, event);
/* ERRORS */
not_ours:
{
GST_DEBUG ("collect_pads not ours");
return FALSE;
}
}
static GstFlowReturn
gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer)
{
GstCollectData *data;
GstCollectPads *pads;
guint64 size;
GstFlowReturn ret;
GST_DEBUG ("Got buffer for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
/* some magic to get the managing collect_pads */
data = (GstCollectData *) gst_pad_get_element_private (pad);
if (data == NULL)
goto not_ours;
pads = data->collect;
size = GST_BUFFER_SIZE (buffer);
GST_OBJECT_LOCK (pads);
/* if not started, bail out */
if (!pads->started)
goto not_started;
/* Call the collected callback until a pad with a buffer is popped. */
while (((pads->queuedpads + pads->eospads) == pads->numpads) && pads->func)
ret = pads->func (pads, pads->user_data);
/* queue buffer on this pad, block if filled */
while (data->buffer != NULL) {
GST_DEBUG ("Pad %s:%s already has a buffer queued, waiting",
GST_DEBUG_PAD_NAME (pad));
GST_COLLECT_PADS_WAIT (pads);
GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad));
/* after a signal, we could be stopped */
if (!pads->started)
goto not_started;
}
GST_DEBUG ("Queuing buffer %p for pad %s:%s", buffer,
GST_DEBUG_PAD_NAME (pad));
pads->queuedpads++;
gst_buffer_replace (&data->buffer, buffer);
/* if all pads have data and we have a function, call it */
if (((pads->queuedpads + pads->eospads) == pads->numpads) && pads->func) {
GST_DEBUG ("All active pads have data, calling %s",
GST_DEBUG_FUNCPTR_NAME (pads->func));
ret = pads->func (pads, pads->user_data);
} else {
GST_DEBUG ("Not all active pads have data, continuing");
ret = GST_FLOW_OK;
}
GST_OBJECT_UNLOCK (pads);
return ret;
/* ERRORS */
not_ours:
{
GST_DEBUG ("collect_pads not ours");
return GST_FLOW_ERROR;
}
not_started:
{
GST_OBJECT_UNLOCK (pads);
GST_DEBUG ("collect_pads not started");
return GST_FLOW_WRONG_STATE;
}
}

View file

@ -1,149 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstcollect_pads.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_COLLECT_PADS_H__
#define __GST_COLLECT_PADS_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_COLLECT_PADS (gst_collect_pads_get_type())
#define GST_COLLECT_PADS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECT_PADS,GstCollectPads))
#define GST_COLLECT_PADS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECT_PADS,GstCollectPadsClass))
#define GST_COLLECT_PADS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_COLLECT_PADS,GstCollectPadsClass))
#define GST_IS_COLLECT_PADS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECT_PADS))
#define GST_IS_COLLECT_PADS_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECT_PADS))
typedef struct _GstCollectData GstCollectData;
typedef struct _GstCollectPads GstCollectPads;
typedef struct _GstCollectPadsClass GstCollectPadsClass;
/**
* GstCollectData:
* @collect: owner #GstCollectPads
* @pad: #GstPad managed by this data
* @buffer: currently queued buffer.
* @pos: position in the buffer
* @segment: last segment received.
*
* Structure used by the collect_pads.
*/
struct _GstCollectData
{
GstCollectPads *collect;
GstPad *pad;
GstBuffer *buffer;
guint pos;
GstSegment segment;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/**
* GstCollectPadsFunction:
* @pads: the #GstCollectPads that trigered the callback
* @user_data: user data passed to gst_collect_pads_set_function()
*
* A function that will be called when all pads have received data.
*
* Returns: GST_FLOW_OK for success
*/
typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data);
#define GST_COLLECT_PADS_GET_COND(pads) (((GstCollectPads *)pads)->cond)
#define GST_COLLECT_PADS_WAIT(pads) (g_cond_wait (GST_COLLECT_PADS_GET_COND (pads), GST_OBJECT_GET_LOCK (pads)))
#define GST_COLLECT_PADS_SIGNAL(pads) (g_cond_signal (GST_COLLECT_PADS_GET_COND (pads)))
#define GST_COLLECT_PADS_BROADCAST(pads)(g_cond_broadcast (GST_COLLECT_PADS_GET_COND (pads)))
/**
* GstCollectPads:
* @data: #GList of #GstCollectData managed by this #GstCollectPads.
*
* Collectpads object.
*/
struct _GstCollectPads {
GstObject object;
/*< public >*/ /* with LOCK */
GSList *data;
/*< private >*/
guint32 cookie;
GCond *cond; /* to signal removal of data */
GstCollectPadsFunction func; /* function and user_data for callback */
gpointer user_data;
guint numpads; /* number of pads */
guint queuedpads; /* number of pads with a buffer */
guint eospads; /* number of pads that are EOS */
gboolean started;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstCollectPadsClass {
GstObjectClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_collect_pads_get_type(void);
/* creating the object */
GstCollectPads* gst_collect_pads_new (void);
/* set the callback */
void gst_collect_pads_set_function (GstCollectPads *pads, GstCollectPadsFunction func,
gpointer user_data);
/* pad management */
GstCollectData* gst_collect_pads_add_pad (GstCollectPads *pads, GstPad *pad, guint size);
gboolean gst_collect_pads_remove_pad (GstCollectPads *pads, GstPad *pad);
gboolean gst_collect_pads_is_active (GstCollectPads *pads, GstPad *pad);
/* start/stop collection */
GstFlowReturn gst_collect_pads_collect (GstCollectPads *pads);
GstFlowReturn gst_collect_pads_collect_range (GstCollectPads *pads, guint64 offset, guint length);
void gst_collect_pads_start (GstCollectPads *pads);
void gst_collect_pads_stop (GstCollectPads *pads);
/* get collected buffers */
GstBuffer* gst_collect_pads_peek (GstCollectPads *pads, GstCollectData *data);
GstBuffer* gst_collect_pads_pop (GstCollectPads *pads, GstCollectData *data);
/* get collected bytes */
guint gst_collect_pads_available (GstCollectPads *pads);
guint gst_collect_pads_read (GstCollectPads *pads, GstCollectData *data,
guint8 **bytes, guint size);
guint gst_collect_pads_flush (GstCollectPads *pads, GstCollectData *data,
guint size);
G_END_DECLS
#endif /* __GST_COLLECT_PADS_H__ */

View file

@ -1,104 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000,2005 Wim Taymans <wim@fluendo.com>
*
* gstpushsrc.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.
*/
/**
* SECTION:gstpushsrc
* @short_description: Base class for push based source elements
* @see_also: #GstBaseSrc
*
* This class is mostly useful for elements that cannot do
* random access, or at least very slowly. The source usually
* prefers to push out a fixed size buffer.
*
* Classes extending this base class will usually be scheduled
* in a push based mode. It the peer accepts to operate without
* offsets and withing the limits of the allowed block size, this
* class can operate in getrange based mode automatically.
*
* The subclass should extend the methods from the baseclass in
* addition to the create method.
*
* Seeking, flushing, scheduling and sync is all handled by this
* base class.
*/
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gstpushsrc.h"
#include "gsttypefindhelper.h"
#include <gst/gstmarshal.h>
GST_DEBUG_CATEGORY_STATIC (gst_push_src_debug);
#define GST_CAT_DEFAULT gst_push_src_debug
#define _do_init(type) \
GST_DEBUG_CATEGORY_INIT (gst_push_src_debug, "pushsrc", 0, \
"pushsrc element");
GST_BOILERPLATE_FULL (GstPushSrc, gst_push_src, GstBaseSrc, GST_TYPE_BASE_SRC,
_do_init);
static GstFlowReturn gst_push_src_create (GstBaseSrc * bsrc, guint64 offset,
guint length, GstBuffer ** ret);
static void
gst_push_src_base_init (gpointer g_class)
{
/* nop */
}
static void
gst_push_src_class_init (GstPushSrcClass * klass)
{
GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass;
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_push_src_create);
}
static void
gst_push_src_init (GstPushSrc * pushsrc, GstPushSrcClass * klass)
{
/* nop */
}
static GstFlowReturn
gst_push_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFlowReturn fret;
GstPushSrc *src;
GstPushSrcClass *pclass;
src = GST_PUSH_SRC (bsrc);
pclass = GST_PUSH_SRC_GET_CLASS (src);
if (pclass->create)
fret = pclass->create (src, ret);
else
fret = GST_FLOW_ERROR;
return fret;
}

View file

@ -1,68 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstpushsrc.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_PUSH_SRC_H__
#define __GST_PUSH_SRC_H__
#include <gst/gst.h>
#include <gst/base/gstbasesrc.h>
G_BEGIN_DECLS
#define GST_TYPE_PUSH_SRC (gst_push_src_get_type())
#define GST_PUSH_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PUSH_SRC,GstPushSrc))
#define GST_PUSH_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PUSH_SRC,GstPushSrcClass))
#define GST_PUSH_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PUSH_SRC, GstPushSrcClass))
#define GST_IS_PUSH_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PUSH_SRC))
#define GST_IS_PUSH_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PUSH_SRC))
typedef struct _GstPushSrc GstPushSrc;
typedef struct _GstPushSrcClass GstPushSrcClass;
/**
* GstPushSrc:
*
* The opaque #GstPushSrc data structure.
*/
struct _GstPushSrc {
GstBaseSrc parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstPushSrcClass {
GstBaseSrcClass parent_class;
/* ask the subclass to create a buffer */
GstFlowReturn (*create) (GstPushSrc *src, GstBuffer **buf);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_push_src_get_type(void);
G_END_DECLS
#endif /* __GST_PUSH_SRC_H__ */

View file

@ -1,182 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000,2005 Wim Taymans <wim@fluendo.com>
*
* gsttypefindhelper.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 <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gsttypefindhelper.h"
/**
* typefind code here
*/
typedef struct
{
GstPad *src;
guint best_probability;
GstCaps *caps;
guint64 size;
GSList *buffers;
GstTypeFindFactory *factory;
}
GstTypeFindHelper;
static guint8 *
helper_find_peek (gpointer data, gint64 offset, guint size)
{
GstTypeFindHelper *find;
GstBuffer *buffer;
GstPad *src;
GstFlowReturn ret;
find = (GstTypeFindHelper *) data;
src = find->src;
GST_LOG_OBJECT (src, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
GST_PLUGIN_FEATURE_NAME (find->factory), offset, size);
if (size == 0)
return NULL;
if (offset < 0) {
if (find->size == -1 || find->size < -offset)
return NULL;
offset += find->size;
}
/* see if we have a matching buffer already in our list */
if (size > 0) {
GSList *walk;
for (walk = find->buffers; walk; walk = walk->next) {
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
guint64 buf_offset = GST_BUFFER_OFFSET (buf);
guint buf_size = GST_BUFFER_SIZE (buf);
if (buf_offset <= offset && (offset + size) < (buf_offset + buf_size))
return GST_BUFFER_DATA (buf) + (offset - buf_offset);
}
}
buffer = NULL;
ret = GST_PAD_GETRANGEFUNC (src) (src, offset, size, &buffer);
if (ret != GST_FLOW_OK)
goto error;
/* getrange might silently return shortened buffers at the end of a file,
* we must, however, always return either the full requested data or NULL */
if (GST_BUFFER_OFFSET (buffer) != offset || GST_BUFFER_SIZE (buffer) < size) {
GST_DEBUG ("droping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT
" instead of %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer) +
GST_BUFFER_SIZE (buffer) - 1, offset, offset + size - 1);
gst_buffer_unref (buffer);
return NULL;
}
find->buffers = g_slist_prepend (find->buffers, buffer);
return GST_BUFFER_DATA (buffer);
error:
{
return NULL;
}
}
static void
helper_find_suggest (gpointer data, guint probability, const GstCaps * caps)
{
GstTypeFindHelper *find = (GstTypeFindHelper *) data;
GST_LOG_OBJECT (find->src,
"'%s' called called suggest (%u, %" GST_PTR_FORMAT ")",
GST_PLUGIN_FEATURE_NAME (find->factory), probability, caps);
if (probability > find->best_probability) {
GstCaps *copy = gst_caps_copy (caps);
gst_caps_replace (&find->caps, copy);
gst_caps_unref (copy);
find->best_probability = probability;
}
}
/**
* gst_type_find_helper:
* @src: A source #GstPad
* @size: The length in bytes
*
* Tries to find what type of data is flowing from the given source #GstPad.
*
* Returns: The #GstCaps corresponding to the data stream.
* Returns #NULL if no #GstCaps matches the data stream.
*/
GstCaps *
gst_type_find_helper (GstPad * src, guint64 size)
{
GstTypeFind gst_find;
GstTypeFindHelper find;
GSList *l;
GList *walk, *type_list = NULL;
GstCaps *result = NULL;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (GST_PAD_GETRANGEFUNC (src) != NULL, NULL);
walk = type_list = gst_type_find_factory_get_list ();
find.src = src;
find.best_probability = 0;
find.caps = NULL;
find.size = size;
find.buffers = NULL;
gst_find.data = &find;
gst_find.peek = helper_find_peek;
gst_find.suggest = helper_find_suggest;
gst_find.get_length = NULL;
while (walk) {
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
find.factory = factory;
gst_type_find_factory_call_function (factory, &gst_find);
if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
break;
walk = g_list_next (walk);
}
if (find.best_probability > 0)
result = find.caps;
for (l = find.buffers; l; l = l->next)
gst_buffer_unref (GST_BUFFER_CAST (l->data));
g_slist_free (find.buffers);
return result;
}

View file

@ -1,34 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000,2005 Wim Taymans <wim@fluendo.com>
*
* gsttypefindhelper.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_TYPEFINDHELPER_H__
#define __GST_TYPEFINDHELPER_H__
#include <gst/gst.h>
G_BEGIN_DECLS
GstCaps * gst_type_find_helper (GstPad *src, guint64 size);
G_END_DECLS
#endif /* __GST_TYPEFINDHELPER_H__ */

View file

@ -1,18 +0,0 @@
lib_LTLIBRARIES = libgstcheck-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_DEPENDENCIES = \
../libgstreamer-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_SOURCES = \
gstcheck.c
libgstcheck_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(CHECK_CFLAGS)
libgstcheck_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) $(CHECK_LIBS) \
../libgstreamer-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_LDFLAGS = \
libgstbase_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
libgstcheck_@GST_MAJORMINOR@includedir = \
$(includedir)/gstreamer-@GST_MAJORMINOR@/gst/check
libgstcheck_@GST_MAJORMINOR@include_HEADERS = \
gstcheck.h

View file

@ -1,249 +0,0 @@
/* GStreamer
*
* Common code for GStreamer unittests
*
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* 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.
*/
/**
* SECTION:gstcheck
* @short_description: Common code for GStreamer unit tests
*
* These macros and functions are for internal use of the unit tests found
* inside the 'check' directories of various GStreamer packages.
*/
#include "gstcheck.h"
GST_DEBUG_CATEGORY (check_debug);
/* logging function for tests
* a test uses g_message() to log a debug line
* a gst unit test can be run with GST_TEST_DEBUG env var set to see the
* messages
*/
gboolean _gst_check_threads_running = FALSE;
GList *thread_list = NULL;
GMutex *mutex;
GCond *start_cond; /* used to notify main thread of thread startups */
GCond *sync_cond; /* used to synchronize all threads and main thread */
gboolean _gst_check_debug = FALSE;
gboolean _gst_check_raised_critical = FALSE;
gboolean _gst_check_raised_warning = FALSE;
gboolean _gst_check_expecting_log = FALSE;
void gst_check_log_message_func
(const gchar * log_domain, GLogLevelFlags log_level,
const gchar * message, gpointer user_data)
{
if (_gst_check_debug) {
g_print ("%s", message);
}
}
void gst_check_log_critical_func
(const gchar * log_domain, GLogLevelFlags log_level,
const gchar * message, gpointer user_data)
{
if (!_gst_check_expecting_log) {
g_print ("\n\nUnexpected critical/warning: %s\n", message);
fail ("Unexpected critical/warning: %s", message);
}
if (_gst_check_debug) {
g_print ("\nExpected critical/warning: %s\n", message);
}
if (log_level & G_LOG_LEVEL_CRITICAL)
_gst_check_raised_critical = TRUE;
if (log_level & G_LOG_LEVEL_WARNING)
_gst_check_raised_warning = TRUE;
}
/* initialize GStreamer testing */
void
gst_check_init (int *argc, char **argv[])
{
gst_init (argc, argv);
GST_DEBUG_CATEGORY_INIT (check_debug, "check", 0, "check regression tests");
if (g_getenv ("GST_TEST_DEBUG"))
_gst_check_debug = TRUE;
g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE, gst_check_log_message_func,
NULL);
g_log_set_handler (NULL, G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
gst_check_log_critical_func, NULL);
g_log_set_handler ("GStreamer", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
gst_check_log_critical_func, NULL);
g_log_set_handler ("GLib-GObject", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
gst_check_log_critical_func, NULL);
}
/* message checking */
void
gst_check_message_error (GstMessage * message, GstMessageType type,
GQuark domain, gint code)
{
GError *error;
gchar *debug;
fail_unless_equals_int (GST_MESSAGE_TYPE (message), type);
gst_message_parse_error (message, &error, &debug);
fail_unless_equals_int (error->domain, domain);
fail_unless_equals_int (error->code, code);
g_error_free (error);
g_free (debug);
}
/* helper functions */
GstFlowReturn
gst_check_chain_func (GstPad * pad, GstBuffer * buffer)
{
GST_DEBUG ("chain_func: received buffer %p", buffer);
buffers = g_list_append (buffers, buffer);
return GST_FLOW_OK;
}
/* setup an element for a filter test with mysrcpad and mysinkpad */
GstElement *
gst_check_setup_element (const gchar * factory)
{
GstElement *element;
GST_DEBUG ("setup_element");
element = gst_element_factory_make (factory, factory);
fail_if (element == NULL, "Could not create a %s", factory);
ASSERT_OBJECT_REFCOUNT (element, factory, 1);
return element;
}
void
gst_check_teardown_element (GstElement * element)
{
GST_DEBUG ("teardown_element");
fail_unless (gst_element_set_state (element, GST_STATE_NULL) ==
GST_STATE_CHANGE_SUCCESS, "could not set to null");
ASSERT_OBJECT_REFCOUNT (element, "element", 1);
gst_object_unref (element);
}
/* FIXME: set_caps isn't that useful
*/
GstPad *
gst_check_setup_src_pad (GstElement * element,
GstStaticPadTemplate * template, GstCaps * caps)
{
GstPad *srcpad, *sinkpad;
GST_DEBUG_OBJECT (element, "setting up sending pad");
/* sending pad */
srcpad = gst_pad_new_from_static_template (template, "src");
fail_if (srcpad == NULL, "Could not create a srcpad");
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
sinkpad = gst_element_get_pad (element, "sink");
fail_if (sinkpad == NULL, "Could not get sink pad from %s",
GST_ELEMENT_NAME (element));
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
if (caps)
fail_unless (gst_pad_set_caps (srcpad, caps));
fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
"Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
gst_object_unref (sinkpad); /* because we got it higher up */
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
return srcpad;
}
void
gst_check_teardown_src_pad (GstElement * element)
{
GstPad *srcpad, *sinkpad;
/* clean up floating src pad */
sinkpad = gst_element_get_pad (element, "sink");
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
srcpad = gst_pad_get_peer (sinkpad);
gst_pad_unlink (srcpad, sinkpad);
/* pad refs held by both creator and this function (through _get) */
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
gst_object_unref (sinkpad);
/* one more ref is held by element itself */
/* pad refs held by both creator and this function (through _get_peer) */
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
gst_object_unref (srcpad);
gst_object_unref (srcpad);
}
/* FIXME: set_caps isn't that useful; might want to check if fixed,
* then use set_use_fixed or somesuch */
GstPad *
gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * template,
GstCaps * caps)
{
GstPad *srcpad, *sinkpad;
GST_DEBUG_OBJECT (element, "setting up receiving pad");
/* receiving pad */
sinkpad = gst_pad_new_from_static_template (template, "sink");
fail_if (sinkpad == NULL, "Could not create a sinkpad");
srcpad = gst_element_get_pad (element, "src");
fail_if (srcpad == NULL, "Could not get source pad from %s",
GST_ELEMENT_NAME (element));
if (caps)
fail_unless (gst_pad_set_caps (sinkpad, caps));
gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
"Could not link %s source and sink pads", GST_ELEMENT_NAME (element));
gst_object_unref (srcpad); /* because we got it higher up */
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
return sinkpad;
}
void
gst_check_teardown_sink_pad (GstElement * element)
{
GstPad *srcpad, *sinkpad;
/* clean up floating sink pad */
srcpad = gst_element_get_pad (element, "src");
sinkpad = gst_pad_get_peer (srcpad);
gst_pad_unlink (srcpad, sinkpad);
/* pad refs held by both creator and this function (through _get_pad) */
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
gst_object_unref (srcpad);
/* one more ref is held by element itself */
/* pad refs held by both creator and this function (through _get_peer) */
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
gst_object_unref (sinkpad);
gst_object_unref (sinkpad);
}

View file

@ -1,262 +0,0 @@
/* GStreamer
*
* Common code for GStreamer unittests
*
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* 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_CHECK_H__
#define __GST_CHECK_H__
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <check.h>
#include <gst/gst.h>
GST_DEBUG_CATEGORY_EXTERN (check_debug);
#define GST_CAT_DEFAULT check_debug
/* logging function for tests
* a test uses g_message() to log a debug line
* a gst unit test can be run with GST_TEST_DEBUG env var set to see the
* messages
*/
extern gboolean _gst_check_threads_running;
extern gboolean _gst_check_raised_critical;
extern gboolean _gst_check_raised_warning;
extern gboolean _gst_check_expecting_log;
/* global variables used in test methods */
GList * buffers;
void gst_check_init (int *argc, char **argv[]);
GstFlowReturn gst_check_chain_func (GstPad *pad, GstBuffer *buffer);
void gst_check_message_error (GstMessage *message, GstMessageType type, GQuark domain, gint code);
GstElement * gst_check_setup_element (const gchar *factory);
void gst_check_teardown_element (GstElement *element);
GstPad * gst_check_setup_src_pad (GstElement *element,
GstStaticPadTemplate *template, GstCaps *caps);
void gst_check_teardown_src_pad (GstElement *element);
GstPad * gst_check_setup_sink_pad (GstElement *element,
GstStaticPadTemplate *template, GstCaps *caps);
void gst_check_teardown_sink_pad (GstElement *element);
#define fail_unless_message_error(msg, domain, code) \
gst_check_message_error (msg, GST_MESSAGE_ERROR, \
GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code)
/***
* wrappers for START_TEST and END_TEST
*/
#define GST_START_TEST(__testname) \
static void __testname (void)\
{\
GST_DEBUG ("test start"); \
tcase_fn_start (""# __testname, __FILE__, __LINE__);
#define GST_END_TEST END_TEST
/* additional fail macros */
#define fail_unless_equals_int(a, b) \
G_STMT_START { \
int first = a; \
int second = b; \
fail_unless(first == second, \
"'" #a "' (%d) is not equal to '" #b"' (%d)", first, second); \
} G_STMT_END;
#define fail_unless_equals_uint64(a, b) \
G_STMT_START { \
guint64 first = a; \
guint64 second = b; \
fail_unless(first == second, \
"'" #a "' (%" G_GUINT64_FORMAT ") is not equal to '" #b"' (%" \
G_GUINT64_FORMAT ")", first, second); \
} G_STMT_END;
#define fail_unless_equals_string(a, b) \
G_STMT_START { \
gchar * first = a; \
gchar * second = b; \
fail_unless(strcmp (first, second) == 0, \
"'" #a "' (%s) is not equal to '" #b"' (%s)", first, second); \
} G_STMT_END;
/***
* thread test macros and variables
*/
extern GList *thread_list;
extern GMutex *mutex;
extern GCond *start_cond; /* used to notify main thread of thread startups */
extern GCond *sync_cond; /* used to synchronize all threads and main thread */
#define MAIN_START_THREADS(count, function, data) \
MAIN_INIT(); \
MAIN_START_THREAD_FUNCTIONS(count, function, data); \
MAIN_SYNCHRONIZE();
#define MAIN_INIT() \
G_STMT_START { \
_gst_check_threads_running = TRUE; \
\
mutex = g_mutex_new (); \
start_cond = g_cond_new (); \
sync_cond = g_cond_new (); \
} G_STMT_END;
#define MAIN_START_THREAD_FUNCTIONS(count, function, data) \
G_STMT_START { \
int i; \
for (i = 0; i < count; ++i) { \
MAIN_START_THREAD_FUNCTION (i, function, data); \
} \
} G_STMT_END;
#define MAIN_START_THREAD_FUNCTION(i, function, data) \
G_STMT_START { \
GThread *thread = NULL; \
GST_DEBUG ("MAIN: creating thread %d", i); \
g_mutex_lock (mutex); \
thread = g_thread_create ((GThreadFunc) function, data, \
TRUE, NULL); \
/* wait for thread to signal us that it's ready */ \
GST_DEBUG ("MAIN: waiting for thread %d", i); \
g_cond_wait (start_cond, mutex); \
g_mutex_unlock (mutex); \
\
thread_list = g_list_append (thread_list, thread); \
} G_STMT_END;
#define MAIN_SYNCHRONIZE() \
G_STMT_START { \
GST_DEBUG ("MAIN: synchronizing"); \
g_cond_broadcast (sync_cond); \
GST_DEBUG ("MAIN: synchronized"); \
} G_STMT_END;
#define MAIN_STOP_THREADS() \
G_STMT_START { \
_gst_check_threads_running = FALSE; \
\
/* join all threads */ \
GST_DEBUG ("MAIN: joining"); \
g_list_foreach (thread_list, (GFunc) g_thread_join, NULL); \
GST_DEBUG ("MAIN: joined"); \
} G_STMT_END;
#define THREAD_START() \
THREAD_STARTED(); \
THREAD_SYNCHRONIZE();
#define THREAD_STARTED() \
G_STMT_START { \
/* signal main thread that we started */ \
GST_DEBUG ("THREAD %p: started", g_thread_self ()); \
g_mutex_lock (mutex); \
g_cond_signal (start_cond); \
} G_STMT_END;
#define THREAD_SYNCHRONIZE() \
G_STMT_START { \
/* synchronize everyone */ \
GST_DEBUG ("THREAD %p: syncing", g_thread_self ()); \
g_cond_wait (sync_cond, mutex); \
GST_DEBUG ("THREAD %p: synced", g_thread_self ()); \
g_mutex_unlock (mutex); \
} G_STMT_END;
#define THREAD_SWITCH() \
G_STMT_START { \
/* a minimal sleep is a context switch */ \
g_usleep (1); \
} G_STMT_END;
#define THREAD_TEST_RUNNING() (_gst_check_threads_running == TRUE)
/* additional assertions */
#define ASSERT_CRITICAL(code) \
G_STMT_START { \
_gst_check_expecting_log = TRUE; \
_gst_check_raised_critical = FALSE; \
code; \
_fail_unless (_gst_check_raised_critical, __FILE__, __LINE__, \
"Expected g_critical, got nothing"); \
_gst_check_expecting_log = FALSE; \
} G_STMT_END
#define ASSERT_WARNING(code) \
G_STMT_START { \
_gst_check_expecting_log = TRUE; \
_gst_check_raised_warning = FALSE; \
code; \
_fail_unless (_gst_check_raised_warning, __FILE__, __LINE__, \
"Expected g_warning, got nothing"); \
_gst_check_expecting_log = FALSE; \
} G_STMT_END
#define ASSERT_OBJECT_REFCOUNT(object, name, value) \
G_STMT_START { \
int rc; \
rc = GST_OBJECT_REFCOUNT_VALUE (object); \
fail_unless (rc == value, \
"%s (%p) refcount is %d instead of %d", \
name, object, rc, value); \
} G_STMT_END
#define ASSERT_OBJECT_REFCOUNT_BETWEEN(object, name, lower, upper) \
G_STMT_START { \
int rc = GST_OBJECT_REFCOUNT_VALUE (object); \
int lo = lower; \
int hi = upper; \
\
fail_unless (rc >= lo, \
"%s (%p) refcount %d is smaller than %d", \
name, object, rc, lo); \
fail_unless (rc <= hi, \
"%s (%p) refcount %d is bigger than %d", \
name, object, rc, hi); \
} G_STMT_END
#define ASSERT_CAPS_REFCOUNT(caps, name, value) \
ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value)
#define ASSERT_BUFFER_REFCOUNT(buffer, name, value) \
ASSERT_MINI_OBJECT_REFCOUNT(buffer, name, value)
#define ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value) \
G_STMT_START { \
int rc; \
rc = GST_MINI_OBJECT_REFCOUNT_VALUE (caps); \
fail_unless (rc == value, \
name " refcount is %d instead of %d", rc, value);\
} G_STMT_END
#endif /* __GST_CHECK_H__ */

View file

@ -1,18 +0,0 @@
lib_LTLIBRARIES = libgstnet-@GST_MAJORMINOR@.la
libgstnet_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/net
libgstnet_@GST_MAJORMINOR@_include_HEADERS = \
gstnet.h \
gstnetclientclock.h \
gstnettimepacket.h \
gstnettimeprovider.h
libgstnet_@GST_MAJORMINOR@_la_SOURCES = \
gstnetclientclock.c \
gstnettimepacket.c \
gstnettimeprovider.c
libgstnet_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstnet_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS)
libgstnet_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)

View file

@ -1,30 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
*
* 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_NET_H__
#define __GST_NET_H__
#include <gst/net/gstnetclientclock.h>
#include <gst/net/gstnettimepacket.h>
#include <gst/net/gstnettimeprovider.h>
#endif /* __GST_NET_H__ */

View file

@ -1,597 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2005 Wim Taymans <wim@fluendo.com>
* 2005 Andy Wingo <wingo@pobox.com>
*
* gstnetclientclock.h: clock that synchronizes itself to a time provider over
* the network
*
* 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.
*/
/**
* SECTION:gstnetclientclock
* @short_description: Special clock that synchronizes to a remote time
* provider.
* @see_also: #GstClock, #GstNetTimeProvider, #GstPipeline
*
* This object implements a custom #GstClock that synchronizes its time
* to a remote time provider such as #GstNetTimeProvider.
*
* A new clock is created with gst_net_client_clock_new() which takes the
* address and port of the remote time provider along with a name and
* an initial time.
*
* This clock will poll the time provider and will update its calibration
* parameters based on the local and remote observations.
*
* Various parameters of the clock can be configured with the parent #GstClock
* "timeout", "window-size" and "window-threshold" object properties.
*
* A #GstNetClientClock is typically set on a #GstPipeline with
* gst_pipeline_use_clock().
*
* Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include "gstnettimepacket.h"
#include "gstnetclientclock.h"
GST_DEBUG_CATEGORY (ncc_debug);
#define GST_CAT_DEFAULT (ncc_debug)
/* #define DEBUGGING_ENABLED */
#ifdef DEBUGGING_ENABLED
#define DEBUG(x, args...) g_print (x "\n", ##args)
#else
#define DEBUG(x, args...) /* nop */
#endif
/* the select call is also performed on the control sockets, that way
* we can send special commands to unblock or restart the select call */
#define CONTROL_RESTART 'R' /* restart the select call */
#define CONTROL_STOP 'S' /* stop the select call */
#define CONTROL_SOCKETS(self) self->control_sock
#define WRITE_SOCKET(self) self->control_sock[1]
#define READ_SOCKET(self) self->control_sock[0]
#define SEND_COMMAND(self, command) \
G_STMT_START { \
unsigned char c; c = command; \
write (WRITE_SOCKET(self), &c, 1); \
} G_STMT_END
#define READ_COMMAND(self, command, res) \
G_STMT_START { \
res = read(READ_SOCKET(self), &command, 1); \
} G_STMT_END
#define DEFAULT_ADDRESS "127.0.0.1"
#define DEFAULT_PORT 5637
#define DEFAULT_TIMEOUT GST_SECOND
enum
{
PROP_0,
PROP_ADDRESS,
PROP_PORT,
};
#define _do_init(type) \
GST_DEBUG_CATEGORY_INIT (ncc_debug, "netclock", 0, "Network client clock");
GST_BOILERPLATE_FULL (GstNetClientClock, gst_net_client_clock,
GstSystemClock, GST_TYPE_SYSTEM_CLOCK, _do_init);
static void gst_net_client_clock_finalize (GObject * object);
static void gst_net_client_clock_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_net_client_clock_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_net_client_clock_stop (GstNetClientClock * self);
static void
gst_net_client_clock_base_init (gpointer g_class)
{
/* nop */
}
static void
gst_net_client_clock_class_init (GstNetClientClockClass * klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass;
gobject_class->finalize = gst_net_client_clock_finalize;
gobject_class->get_property = gst_net_client_clock_get_property;
gobject_class->set_property = gst_net_client_clock_set_property;
g_object_class_install_property (gobject_class, PROP_ADDRESS,
g_param_spec_string ("address", "address",
"The address of the machine providing a time server, "
"as a dotted quad (x.x.x.x)", DEFAULT_ADDRESS, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT,
g_param_spec_int ("port", "port",
"The port on which the remote server is listening", 0, G_MAXUINT16,
DEFAULT_PORT, G_PARAM_READWRITE));
}
static void
gst_net_client_clock_init (GstNetClientClock * self,
GstNetClientClockClass * g_class)
{
GstClock *clock = GST_CLOCK_CAST (self);
self->port = DEFAULT_PORT;
self->address = g_strdup (DEFAULT_ADDRESS);
clock->timeout = DEFAULT_TIMEOUT;
self->sock = -1;
self->thread = NULL;
self->servaddr = NULL;
READ_SOCKET (self) = -1;
WRITE_SOCKET (self) = -1;
}
static void
gst_net_client_clock_finalize (GObject * object)
{
GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
if (self->thread) {
gst_net_client_clock_stop (self);
g_assert (self->thread == NULL);
}
if (READ_SOCKET (self) != -1) {
close (READ_SOCKET (self));
close (WRITE_SOCKET (self));
READ_SOCKET (self) = -1;
WRITE_SOCKET (self) = -1;
}
g_free (self->address);
self->address = NULL;
g_free (self->servaddr);
self->servaddr = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_net_client_clock_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
switch (prop_id) {
case PROP_ADDRESS:
g_free (self->address);
if (g_value_get_string (value) == NULL)
self->address = g_strdup (DEFAULT_ADDRESS);
else
self->address = g_strdup (g_value_get_string (value));
break;
case PROP_PORT:
self->port = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_net_client_clock_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
switch (prop_id) {
case PROP_ADDRESS:
g_value_set_string (value, self->address);
break;
case PROP_PORT:
g_value_set_int (value, self->port);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_net_client_clock_observe_times (GstNetClientClock * self,
GstClockTime local_1, GstClockTime remote, GstClockTime local_2)
{
GstClockTime local_avg;
gdouble r_squared;
GstClock *clock;
if (local_2 < local_1)
goto bogus_observation;
local_avg = (local_2 + local_1) / 2;
clock = GST_CLOCK_CAST (self);
gst_clock_add_observation (GST_CLOCK (self), local_avg, remote, &r_squared);
GST_CLOCK_SLAVE_LOCK (self);
if (clock->filling) {
self->current_timeout = 0;
} else {
/* geto formula */
self->current_timeout =
(1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
self->current_timeout = MIN (self->current_timeout, clock->timeout);
}
GST_CLOCK_SLAVE_UNLOCK (clock);
return;
bogus_observation:
{
GST_WARNING_OBJECT (self, "time packet receive time < send time (%",
GST_TIME_FORMAT, " < %" GST_TIME_FORMAT ")", GST_TIME_ARGS (local_1),
GST_TIME_ARGS (local_2));
return;
}
}
static gint
gst_net_client_clock_do_select (GstNetClientClock * self, fd_set * readfds)
{
gint max_sock;
gint ret;
while (TRUE) {
FD_ZERO (readfds);
FD_SET (self->sock, readfds);
FD_SET (READ_SOCKET (self), readfds);
max_sock = MAX (self->sock, READ_SOCKET (self));
GST_LOG_OBJECT (self, "doing select");
{
GstClockTime diff;
GTimeVal tv, *ptv = &tv;
diff = gst_clock_get_internal_time (GST_CLOCK (self));
GST_TIME_TO_TIMEVAL (self->current_timeout, tv);
ret = select (max_sock + 1, readfds, NULL, NULL, (struct timeval *) ptv);
diff = gst_clock_get_internal_time (GST_CLOCK (self)) - diff;
if (diff > self->current_timeout)
self->current_timeout = 0;
else
self->current_timeout -= diff;
}
GST_LOG_OBJECT (self, "select returned %d", ret);
if (ret < 0) {
if (errno != EAGAIN && errno != EINTR)
goto select_error;
else
continue;
} else {
return ret;
}
g_assert_not_reached ();
/* log errors and keep going */
select_error:
{
GST_WARNING_OBJECT (self, "select error %d: %s (%d)", ret,
g_strerror (errno), errno);
continue;
}
}
g_assert_not_reached ();
return -1;
}
static gpointer
gst_net_client_clock_thread (gpointer data)
{
GstNetClientClock *self = data;
struct sockaddr_in tmpaddr;
socklen_t len;
fd_set read_fds;
GstNetTimePacket *packet;
gint ret;
GstClock *clock = data;
while (TRUE) {
ret = gst_net_client_clock_do_select (self, &read_fds);
if (FD_ISSET (READ_SOCKET (self), &read_fds)) {
/* got control message */
while (TRUE) {
gchar command;
int res;
READ_COMMAND (self, command, res);
if (res < 0) {
GST_LOG_OBJECT (self, "no more commands");
break;
}
DEBUG ("control message: '%c'", command);
switch (command) {
case CONTROL_STOP:
/* break out of the select loop */
GST_LOG_OBJECT (self, "stop");
goto stopped;
default:
GST_WARNING_OBJECT (self, "unknown message: '%c'", command);
g_warning ("netclientclock: unknown control message received");
continue;
}
g_assert_not_reached ();
}
continue;
} else if (ret == 0) {
/* timed out, let's send another packet */
DEBUG ("timed out");
packet = gst_net_time_packet_new (NULL);
packet->local_time = gst_clock_get_internal_time (GST_CLOCK (self));
DEBUG ("sending packet, local time = %" GST_TIME_FORMAT,
GST_TIME_ARGS (packet->local_time));
gst_net_time_packet_send (packet, self->sock,
(struct sockaddr *) self->servaddr, sizeof (struct sockaddr_in));
g_free (packet);
/* reset timeout */
self->current_timeout = clock->timeout;
continue;
} else if (FD_ISSET (self->sock, &read_fds)) {
/* got data in */
GstClockTime new_local = gst_clock_get_internal_time (GST_CLOCK (self));
len = sizeof (struct sockaddr);
packet = gst_net_time_packet_receive (self->sock,
(struct sockaddr *) &tmpaddr, &len);
if (!packet)
goto receive_error;
DEBUG ("got packet back");
DEBUG ("local_1 = %" GST_TIME_FORMAT, GST_TIME_ARGS (packet->local_time));
DEBUG ("remote = %" GST_TIME_FORMAT, GST_TIME_ARGS (packet->remote_time));
DEBUG ("local_2 = %" GST_TIME_FORMAT, GST_TIME_ARGS (new_local));
/* observe_times will reset the timeout */
gst_net_client_clock_observe_times (self, packet->local_time,
packet->remote_time, new_local);
g_free (packet);
continue;
} else {
GST_WARNING_OBJECT (self, "unhandled select return state?");
continue;
}
g_assert_not_reached ();
stopped:
{
GST_DEBUG_OBJECT (self, "shutting down");
/* socket gets closed in _stop() */
return NULL;
}
receive_error:
{
GST_WARNING_OBJECT (self, "receive error");
continue;
}
g_assert_not_reached ();
}
g_assert_not_reached ();
return NULL;
}
static gboolean
gst_net_client_clock_start (GstNetClientClock * self)
{
struct sockaddr_in servaddr, myaddr;
socklen_t len;
gint ret;
GError *error;
g_return_val_if_fail (self->address != NULL, FALSE);
g_return_val_if_fail (self->servaddr == NULL, FALSE);
if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
goto no_socket;
self->sock = ret;
len = sizeof (myaddr);
ret = getsockname (self->sock, (struct sockaddr *) &myaddr, &len);
if (ret < 0)
goto getsockname_error;
GST_DEBUG_OBJECT (self, "socket opened on UDP port %hd",
ntohs (servaddr.sin_port));
memset (&servaddr, 0, sizeof (servaddr));
servaddr.sin_family = AF_INET; /* host byte order */
servaddr.sin_port = htons (self->port); /* short, network byte order */
if (!inet_aton (self->address, &servaddr.sin_addr))
goto bad_address;
self->servaddr = g_malloc (sizeof (struct sockaddr_in));
memcpy (self->servaddr, &servaddr, sizeof (servaddr));
GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address,
self->port);
self->thread = g_thread_create (gst_net_client_clock_thread, self, TRUE,
&error);
if (!self->thread)
goto no_thread;
return TRUE;
/* ERRORS */
no_socket:
{
GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
g_strerror (errno), errno);
return FALSE;
}
getsockname_error:
{
GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
g_strerror (errno), errno);
close (self->sock);
self->sock = -1;
return FALSE;
}
bad_address:
{
GST_ERROR_OBJECT (self, "inet_aton failed %d: %s (%d)", ret,
g_strerror (errno), errno);
close (self->sock);
self->sock = -1;
return FALSE;
}
no_thread:
{
GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
close (self->sock);
self->sock = -1;
g_free (self->servaddr);
self->servaddr = NULL;
g_error_free (error);
return FALSE;
}
}
static void
gst_net_client_clock_stop (GstNetClientClock * self)
{
SEND_COMMAND (self, CONTROL_STOP);
g_thread_join (self->thread);
self->thread = NULL;
if (self->sock != -1) {
close (self->sock);
self->sock = -1;
}
}
/**
* gst_net_client_clock_new:
* @name: a name for the clock
* @remote_address: the address of the remote clock provider
* @remote_port: the port of the remote clock provider
* @base_time: initial time of the clock
*
* Create a new #GstNetClientClock that will report the time
* provided by the #GstNetClockProvider on @remote_address and
* @remote_port.
*
* Returns: a new #GstClock that receives a time from the remote
* clock.
*/
GstClock *
gst_net_client_clock_new (gchar * name, const gchar * remote_address,
gint remote_port, GstClockTime base_time)
{
GstNetClientClock *ret;
GstClockTime internal;
gint iret;
g_return_val_if_fail (remote_address != NULL, NULL);
g_return_val_if_fail (remote_port > 0, NULL);
g_return_val_if_fail (remote_port <= G_MAXUINT16, NULL);
g_return_val_if_fail (base_time != GST_CLOCK_TIME_NONE, NULL);
ret = g_object_new (GST_TYPE_NET_CLIENT_CLOCK, "address", remote_address,
"port", remote_port, NULL);
/* gst_clock_get_time() values are guaranteed to be increasing. because no one
* has called get_time on this clock yet we are free to adjust to any value
* without worrying about worrying about MAX() issues with the clock's
* internal time.
*/
/* update our internal time so get_time() give something around base_time.
assume that the rate is 1 in the beginning. */
internal = gst_clock_get_internal_time (GST_CLOCK (ret));
gst_clock_set_calibration (GST_CLOCK (ret), internal, base_time, 1, 1);
{
GstClockTime now = gst_clock_get_time (GST_CLOCK (ret));
if (now < base_time || now > base_time + GST_SECOND)
g_warning ("unable to set the base time, expect sync problems!");
}
GST_DEBUG_OBJECT (ret, "creating socket pair");
if ((iret = socketpair (PF_UNIX, SOCK_STREAM, 0, CONTROL_SOCKETS (ret))) < 0)
goto no_socket_pair;
fcntl (READ_SOCKET (ret), F_SETFL, O_NONBLOCK);
fcntl (WRITE_SOCKET (ret), F_SETFL, O_NONBLOCK);
if (!gst_net_client_clock_start (ret))
goto failed_start;
/* all systems go, cap'n */
return (GstClock *) ret;
no_socket_pair:
{
GST_ERROR_OBJECT (ret, "no socket pair %d: %s (%d)", iret,
g_strerror (errno), errno);
gst_object_unref (ret);
return NULL;
}
failed_start:
{
/* already printed a nice error */
gst_object_unref (ret);
return NULL;
}
}

View file

@ -1,97 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2005 Wim Taymans <wim@fluendo.com>
* 2005 Andy Wingo <wingo@pobox.com>
*
* gstnetclientclock.h: clock that synchronizes itself to a time provider over
* the network
*
* 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_NET_CLIENT_CLOCK_H__
#define __GST_NET_CLIENT_CLOCK_H__
#include <gst/gst.h>
#include <gst/gstsystemclock.h>
G_BEGIN_DECLS
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define GST_TYPE_NET_CLIENT_CLOCK \
(gst_net_client_clock_get_type())
#define GST_NET_CLIENT_CLOCK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_CLIENT_CLOCK,GstNetClientClock))
#define GST_NET_CLIENT_CLOCK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_CLIENT_CLOCK,GstNetClientClockClass))
#define GST_IS_NET_CLIENT_CLOCK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_CLIENT_CLOCK))
#define GST_IS_NET_CLIENT_CLOCK_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_CLIENT_CLOCK))
typedef struct _GstNetClientClock GstNetClientClock;
typedef struct _GstNetClientClockClass GstNetClientClockClass;
/**
* GstNetClientClock:
*
* Opaque #GstNetClientClock structure.
*/
struct _GstNetClientClock {
GstSystemClock clock;
/*< protected >*/
gchar *address;
gint port;
/*< private >*/
int sock;
int control_sock[2];
GstClockTime current_timeout;
struct sockaddr_id *servaddr;
GThread *thread;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstNetClientClockClass {
GstSystemClockClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_net_client_clock_get_type (void);
GstClock* gst_net_client_clock_new (gchar *name, const gchar *remote_address,
gint remote_port, GstClockTime base_time);
G_END_DECLS
#endif /* __GST_NET_CLIENT_CLOCK_H__ */

View file

@ -1,179 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
*
* 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.
*/
/**
* SECTION:gstnettimepacket
* @short_description: Helper structure to construct clock packets used
* by network clocks.
* @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider
*
* Various functions for receiving, sending an serializing #GstNetTimePacket
* structures.
*
* Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstnettimepacket.h"
/**
* gst_net_time_packet_new:
* @buffer: a buffer from which to construct the packet, or NULL
*
* Creates a new #GstNetTimePacket from a buffer received over the network. The
* caller is responsible for ensuring that @buffer is at least
* #GST_NET_TIME_PACKET_SIZE bytes long.
*
* If @buffer is #NULL, the local and remote times will be set to
* #GST_CLOCK_TIME_NONE.
*
* MT safe. Caller owns return value (g_free to free).
*
* Returns: The new #GstNetTimePacket.
*/
GstNetTimePacket *
gst_net_time_packet_new (const guint8 * buffer)
{
GstNetTimePacket *ret;
g_assert (sizeof (GstClockTime) == 8);
ret = g_new0 (GstNetTimePacket, 1);
if (buffer) {
ret->local_time = GST_READ_UINT64_BE (buffer);
ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime));
} else {
ret->local_time = GST_CLOCK_TIME_NONE;
ret->remote_time = GST_CLOCK_TIME_NONE;
}
return ret;
}
/**
* gst_net_time_packet_serialize:
* @packet: the #GstNetTimePacket
*
* Serialized a #GstNetTimePacket into a newly-allocated sequence of
* #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is
* suitable for passing to write(2) or sendto(2) for communication over the
* network.
*
* MT safe. Caller owns return value (g_free to free).
*
* Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes.
*/
guint8 *
gst_net_time_packet_serialize (const GstNetTimePacket * packet)
{
guint8 *ret;
g_assert (sizeof (GstClockTime) == 8);
ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE);
GST_WRITE_UINT64_BE (ret, packet->local_time);
GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time);
return ret;
}
/**
* gst_net_time_packet_receive:
* @fd: a file descriptor created by socket(2)
* @addr: a pointer to a sockaddr to hold the address of the sender
* @len: a pointer to the size of the data pointed to by @addr
*
* Receives a #GstNetTimePacket over a socket. Handles interrupted system calls,
* but otherwise returns NULL on error. See recvfrom(2) for more information on
* how to interpret @sockaddr.
*
* MT safe. Caller owns return value (g_free to free).
*
* Returns: The new #GstNetTimePacket.
*/
GstNetTimePacket *
gst_net_time_packet_receive (gint fd, struct sockaddr * addr, socklen_t * len)
{
guint8 buffer[GST_NET_TIME_PACKET_SIZE];
gint ret;
while (TRUE) {
ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
0, (struct sockaddr *) addr, len);
if (ret < 0) {
if (errno != EAGAIN && errno != EINTR)
goto receive_error;
else
continue;
} else if (ret < GST_NET_TIME_PACKET_SIZE) {
goto short_packet;
} else {
return gst_net_time_packet_new (buffer);
}
}
receive_error:
{
GST_DEBUG ("receive error %d: %s (%d)", ret, g_strerror (errno), errno);
return NULL;
}
short_packet:
{
GST_DEBUG ("someone sent us a short packet (%d < %d)",
ret, GST_NET_TIME_PACKET_SIZE);
return NULL;
}
}
/**
* gst_net_time_packet_send:
* @packet: the #GstNetTimePacket
* @fd: a file descriptor created by socket(2)
* @addr: a pointer to a sockaddr to hold the address of the sender
* @len: the size of the data pointed to by @addr
*
* Sends a #GstNetTimePacket over a socket. Essentially a thin wrapper around
* sendto(2) and gst_net_time_packet_serialize().
*
* MT safe.
*
* Returns: The return value of sendto(2).
*/
gint
gst_net_time_packet_send (const GstNetTimePacket * packet, gint fd,
struct sockaddr * addr, socklen_t len)
{
guint8 *buffer;
gint ret;
g_return_val_if_fail (packet != NULL, -EINVAL);
buffer = gst_net_time_packet_serialize (packet);
ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, MSG_DONTWAIT, addr, len);
g_free (buffer);
return ret;
}

View file

@ -1,69 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
*
* 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_NET_TIME_PACKET_H__
#define __GST_NET_TIME_PACKET_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/**
* GST_NET_TIME_PACKET_SIZE:
*
* The size of the packets sent between network clocks.
*/
#define GST_NET_TIME_PACKET_SIZE 16
typedef struct _GstNetTimePacket GstNetTimePacket;
/**
* GstNetTimePacket:
* @local_time: the local time when this packet was sent
* @remote_time: the remote time observation
*
* Content of a #GstNetTimePacket.
*/
struct _GstNetTimePacket {
GstClockTime local_time;
GstClockTime remote_time;
};
GstNetTimePacket* gst_net_time_packet_new (const guint8 *buffer);
guint8* gst_net_time_packet_serialize (const GstNetTimePacket *packet);
GstNetTimePacket* gst_net_time_packet_receive (gint fd, struct sockaddr *addr,
socklen_t *len);
gint gst_net_time_packet_send (const GstNetTimePacket *packet,
gint fd, struct sockaddr *addr,
socklen_t len);
G_END_DECLS
#endif /* __GST_NET_TIME_PACKET_H__ */

View file

@ -1,485 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
*
* 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.
*/
/**
* SECTION:gstnettimeprovider
* @short_description: Special object that exposed the time of a clock
* on the network.
* @see_also: #GstClock, #GstNetClientClock, #GstPipeline
*
* This object exposes the time of a #GstClock on the network.
*
* A #GstNetTimeProvider is created with gst_net_time_provider_new() which
* takes a #GstClock, an address and a port numner as arguments.
*
* After creating the object, a client clock such as #GstNetClientClock can
* query the exposed clock for its values.
*
* The #GstNetTimeProvider typically wraps the clock used by a #GstPipeline.
*
* Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstnettimeprovider.h"
#include "gstnettimepacket.h"
#include <unistd.h>
#include <sys/ioctl.h>
#ifdef HAVE_FIONREAD_IN_SYS_FILIO
#include <sys/filio.h>
#endif
GST_DEBUG_CATEGORY (ntp_debug);
#define GST_CAT_DEFAULT (ntp_debug)
/* the select call is also performed on the control sockets, that way
* we can send special commands to unblock or restart the select call */
#define CONTROL_RESTART 'R' /* restart the select call */
#define CONTROL_STOP 'S' /* stop the select call */
#define CONTROL_SOCKETS(self) self->control_sock
#define WRITE_SOCKET(self) self->control_sock[1]
#define READ_SOCKET(self) self->control_sock[0]
#define SEND_COMMAND(self, command) \
G_STMT_START { \
unsigned char c; c = command; \
write (WRITE_SOCKET(self), &c, 1); \
} G_STMT_END
#define READ_COMMAND(self, command, res) \
G_STMT_START { \
res = read(READ_SOCKET(self), &command, 1); \
} G_STMT_END
#define DEFAULT_ADDRESS "0.0.0.0"
#define DEFAULT_PORT 5637
enum
{
PROP_0,
PROP_PORT,
PROP_ADDRESS,
PROP_CLOCK
/* FILL ME */
};
static gboolean gst_net_time_provider_start (GstNetTimeProvider * bself);
static void gst_net_time_provider_stop (GstNetTimeProvider * bself);
static gpointer gst_net_time_provider_thread (gpointer data);
static void gst_net_time_provider_finalize (GObject * object);
static void gst_net_time_provider_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_net_time_provider_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
#define _do_init(type) \
GST_DEBUG_CATEGORY_INIT (ntp_debug, "nettime", 0, "Network time provider");
GST_BOILERPLATE_FULL (GstNetTimeProvider, gst_net_time_provider, GstObject,
GST_TYPE_OBJECT, _do_init);
static void
gst_net_time_provider_base_init (gpointer g_class)
{
g_assert (sizeof (GstClockTime) == 8);
}
static void
gst_net_time_provider_class_init (GstNetTimeProviderClass * klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass;
gobject_class->finalize = gst_net_time_provider_finalize;
gobject_class->set_property = gst_net_time_provider_set_property;
gobject_class->get_property = gst_net_time_provider_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT,
g_param_spec_int ("port", "port",
"The port to receive the packets from, 0=allocate", 0, G_MAXUINT16,
DEFAULT_PORT, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_ADDRESS,
g_param_spec_string ("address", "address",
"The address to bind on, as a dotted quad (x.x.x.x)",
DEFAULT_ADDRESS, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_CLOCK,
g_param_spec_object ("clock", "Clock",
"The clock to export over the network", GST_TYPE_CLOCK,
G_PARAM_READWRITE));
}
static void
gst_net_time_provider_init (GstNetTimeProvider * self,
GstNetTimeProviderClass * g_class)
{
self->port = DEFAULT_PORT;
self->sock = -1;
self->address = g_strdup (DEFAULT_ADDRESS);
self->thread = NULL;
READ_SOCKET (self) = -1;
WRITE_SOCKET (self) = -1;
}
static void
gst_net_time_provider_finalize (GObject * object)
{
GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
if (self->thread) {
gst_net_time_provider_stop (self);
g_assert (self->thread == NULL);
}
if (READ_SOCKET (self) != -1) {
close (READ_SOCKET (self));
close (WRITE_SOCKET (self));
READ_SOCKET (self) = -1;
WRITE_SOCKET (self) = -1;
}
g_free (self->address);
self->address = NULL;
if (self->clock)
gst_object_unref (self->clock);
self->clock = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gpointer
gst_net_time_provider_thread (gpointer data)
{
GstNetTimeProvider *self = data;
struct sockaddr_in tmpaddr;
socklen_t len;
fd_set read_fds;
guint max_sock;
GstNetTimePacket *packet;
gint ret;
while (TRUE) {
FD_ZERO (&read_fds);
FD_SET (self->sock, &read_fds);
FD_SET (READ_SOCKET (self), &read_fds);
max_sock = MAX (self->sock, READ_SOCKET (self));
GST_LOG_OBJECT (self, "doing select");
ret = select (max_sock + 1, &read_fds, NULL, NULL, NULL);
GST_LOG_OBJECT (self, "select returned %d", ret);
if (ret <= 0) {
if (errno != EAGAIN && errno != EINTR)
goto select_error;
else
continue;
} else if (FD_ISSET (READ_SOCKET (self), &read_fds)) {
/* got control message */
while (TRUE) {
gchar command;
int res;
READ_COMMAND (self, command, res);
if (res < 0) {
GST_LOG_OBJECT (self, "no more commands");
break;
}
switch (command) {
case CONTROL_STOP:
/* break out of the select loop */
GST_LOG_OBJECT (self, "stop");
goto stopped;
default:
GST_WARNING_OBJECT (self, "unkown");
g_warning ("nettimeprovider: unknown control message received");
continue;
}
g_assert_not_reached ();
}
continue;
} else {
/* got data in */
len = sizeof (struct sockaddr);
packet = gst_net_time_packet_receive (self->sock,
(struct sockaddr *) &tmpaddr, &len);
if (!packet)
goto receive_error;
/* do what we were asked to and send the packet back */
packet->remote_time = gst_clock_get_time (self->clock);
/* ignore errors */
gst_net_time_packet_send (packet, self->sock,
(struct sockaddr *) &tmpaddr, len);
g_free (packet);
continue;
}
g_assert_not_reached ();
/* log errors and keep going */
select_error:
{
GST_DEBUG_OBJECT (self, "select error %d: %s (%d)", ret,
g_strerror (errno), errno);
continue;
}
stopped:
{
GST_DEBUG_OBJECT (self, "shutting down");
/* close socket */
return NULL;
}
receive_error:
{
GST_DEBUG_OBJECT (self, "receive error");
continue;
}
g_assert_not_reached ();
}
g_assert_not_reached ();
return NULL;
}
static void
gst_net_time_provider_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
switch (prop_id) {
case PROP_PORT:
self->port = g_value_get_int (value);
break;
case PROP_ADDRESS:
g_free (self->address);
if (g_value_get_string (value) == NULL)
self->address = g_strdup (DEFAULT_ADDRESS);
else
self->address = g_strdup (g_value_get_string (value));
break;
case PROP_CLOCK:
gst_object_replace ((GstObject **) & self->clock,
(GstObject *) g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_net_time_provider_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
switch (prop_id) {
case PROP_PORT:
g_value_set_int (value, self->port);
break;
case PROP_ADDRESS:
g_value_set_string (value, self->address);
break;
case PROP_CLOCK:
g_value_set_object (value, self->clock);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_net_time_provider_start (GstNetTimeProvider * self)
{
gint ru;
struct sockaddr_in my_addr;
guint len;
int port;
gint ret;
GError *error;
if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
goto no_socket;
self->sock = ret;
ru = 1;
ret = setsockopt (self->sock, SOL_SOCKET, SO_REUSEADDR, &ru, sizeof (ru));
if (ret < 0)
goto setsockopt_error;
memset (&my_addr, 0, sizeof (my_addr));
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons ((gint16) self->port); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY;
if (self->address)
inet_aton (self->address, &my_addr.sin_addr);
GST_DEBUG_OBJECT (self, "binding on port %d", self->port);
ret = bind (self->sock, (struct sockaddr *) &my_addr, sizeof (my_addr));
if (ret < 0)
goto bind_error;
len = sizeof (my_addr);
ret = getsockname (self->sock, (struct sockaddr *) &my_addr, &len);
if (ret < 0)
goto getsockname_error;
port = ntohs (my_addr.sin_port);
GST_DEBUG_OBJECT (self, "bound, on port %d", port);
if (port != self->port) {
self->port = port;
GST_DEBUG_OBJECT (self, "notifying %d", port);
g_object_notify (G_OBJECT (self), "port");
}
self->thread = g_thread_create (gst_net_time_provider_thread, self, TRUE,
&error);
if (!self->thread)
goto no_thread;
return TRUE;
/* ERRORS */
no_socket:
{
GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
g_strerror (errno), errno);
return FALSE;
}
setsockopt_error:
{
close (self->sock);
self->sock = -1;
GST_ERROR_OBJECT (self, "setsockopt failed %d: %s (%d)", ret,
g_strerror (errno), errno);
return FALSE;
}
bind_error:
{
close (self->sock);
self->sock = -1;
GST_ERROR_OBJECT (self, "bind failed %d: %s (%d)", ret,
g_strerror (errno), errno);
return FALSE;
}
getsockname_error:
{
close (self->sock);
self->sock = -1;
GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
g_strerror (errno), errno);
return FALSE;
}
no_thread:
{
close (self->sock);
self->sock = -1;
GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
g_error_free (error);
return FALSE;
}
}
static void
gst_net_time_provider_stop (GstNetTimeProvider * self)
{
SEND_COMMAND (self, CONTROL_STOP);
g_thread_join (self->thread);
self->thread = NULL;
if (self->sock != -1) {
close (self->sock);
self->sock = -1;
}
}
/**
* gst_net_time_provider_new:
* @clock: a #GstClock to export over the network
* @address: an address to bind on as a dotted quad (xxx.xxx.xxx.xxx), or NULL
* to bind to all addresses
* @port: a port to bind on, or -1 to let the kernel choose
*
* Allows network clients to get the current time of @clock.
*
* Returns: The new #GstNetTimeProvider, or NULL on error.
*/
GstNetTimeProvider *
gst_net_time_provider_new (GstClock * clock, const gchar * address, gint port)
{
GstNetTimeProvider *ret;
gint iret;
g_return_val_if_fail (clock && GST_IS_CLOCK (clock), NULL);
g_return_val_if_fail (port >= 0 && port <= G_MAXUINT16, NULL);
ret = g_object_new (GST_TYPE_NET_TIME_PROVIDER, "clock", clock, "address",
address, "port", port, NULL);
GST_DEBUG_OBJECT (ret, "creating socket pair");
if ((iret = socketpair (PF_UNIX, SOCK_STREAM, 0, CONTROL_SOCKETS (ret))) < 0)
goto no_socket_pair;
fcntl (READ_SOCKET (ret), F_SETFL, O_NONBLOCK);
fcntl (WRITE_SOCKET (ret), F_SETFL, O_NONBLOCK);
if (!gst_net_time_provider_start (ret))
goto failed_start;
/* all systems go, cap'n */
return ret;
no_socket_pair:
{
GST_ERROR_OBJECT (ret, "no socket pair %d: %s (%d)", iret,
g_strerror (errno), errno);
gst_object_unref (ret);
return NULL;
}
failed_start:
{
/* already printed a nice error */
gst_object_unref (ret);
return NULL;
}
}

View file

@ -1,87 +0,0 @@
/* GStreamer
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
*
* 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_NET_TIME_PROVIDER_H__
#define __GST_NET_TIME_PROVIDER_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define GST_TYPE_NET_TIME_PROVIDER \
(gst_net_time_provider_get_type())
#define GST_NET_TIME_PROVIDER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_TIME_PROVIDER,GstNetTimeProvider))
#define GST_NET_TIME_PROVIDER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_TIME_PROVIDER,GstNetTimeProvider))
#define GST_IS_NET_TIME_PROVIDER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_TIME_PROVIDER))
#define GST_IS_NET_TIME_PROVIDER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_TIME_PROVIDER))
typedef struct _GstNetTimeProvider GstNetTimeProvider;
typedef struct _GstNetTimeProviderClass GstNetTimeProviderClass;
/**
* GstNetTimeProvider:
*
* Opaque #GstNetTimeProvider structure.
*/
struct _GstNetTimeProvider {
GstObject parent;
/*< private >*/
gchar *address;
int port;
int sock;
int control_sock[2];
GThread *thread;
GstClock *clock;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstNetTimeProviderClass {
GstObjectClass parent_class;
};
GType gst_net_time_provider_get_type (void);
GstNetTimeProvider* gst_net_time_provider_new (GstClock *clock,
const gchar *address,
gint port);
G_END_DECLS
#endif /* __GST_NET_TIME_PROVIDER_H__ */

View file

@ -1 +1,20 @@
SUBDIRS = controller dataprotocol
if HAVE_CHECK
SUBDIRS_CHECK = check
else
SUBDIRS_CHECK =
endif
if GST_DISABLE_NET
SUBDIRS_NET =
else
if HAVE_SYS_SOCKET_H
SUBDIRS_NET = net
else
SUBDIRS_NET =
endif
endif
SUBDIRS_ALWAYS = base controller dataprotocol
SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_NET)
DIST_SUBDIRS = $(SUBDIRS_ALWAYS) check net

View file

@ -1,7 +1,7 @@
lib_LTLIBRARIES = libgstbase-@GST_MAJORMINOR@.la
libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \
../libgstreamer-@GST_MAJORMINOR@.la
$(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la
libgstbase_@GST_MAJORMINOR@_la_SOURCES = \
gstadapter.c \
gstbasesink.c \

View file

@ -188,7 +188,7 @@
#include <stdlib.h>
#include <string.h>
#include "../gst-i18n-lib.h"
#include "../../../gst/gst-i18n-lib.h"
#include "gstbasetransform.h"
#include <gst/gstmarshal.h>

View file

@ -1,13 +1,13 @@
lib_LTLIBRARIES = libgstcheck-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_DEPENDENCIES = \
../libgstreamer-@GST_MAJORMINOR@.la
$(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_SOURCES = \
gstcheck.c
libgstcheck_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(CHECK_CFLAGS)
libgstcheck_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) $(CHECK_LIBS) \
../libgstreamer-@GST_MAJORMINOR@.la
$(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la
libgstcheck_@GST_MAJORMINOR@_la_LDFLAGS = \
libgstbase_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)

View file

@ -28,7 +28,7 @@ libgstelements_la_SOURCES = \
libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstelements_la_LIBADD = \
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS)
libgstelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -6,8 +6,8 @@ gst/gsterror.c
gst/gstqueue.c
gst/gsttaglist.c
gst/parse/grammar.y
gst/base/gstbasesrc.c
gst/base/gstbasesink.c
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasesink.c
plugins/elements/gstfakesink.c
plugins/elements/gstfilesink.c
plugins/elements/gstfilesrc.c

View file

@ -70,7 +70,7 @@ TESTS = $(check_PROGRAMS)
noinst_HEADERS = gst/capslist.h
AM_CFLAGS = $(GST_OBJ_CFLAGS) $(CHECK_CFLAGS)
LDADD = $(top_builddir)/gst/check/libgstcheck-@GST_MAJORMINOR@.la \
LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS) \
$(CHECK_LIBS)
@ -86,10 +86,10 @@ gst_libs_controller_LDADD = \
$(LDADD)
net_gstnetclientclock_LDADD = \
$(top_builddir)/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(LDADD)
net_gstnettimeprovider_LDADD = \
$(top_builddir)/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la \
$(LDADD)
# valgrind testing