mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-14 11:25:39 +00:00
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:
parent
65ce5ed080
commit
a0c4c4812c
40 changed files with 91 additions and 8952 deletions
43
ChangeLog
43
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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= \
|
||||
|
|
|
@ -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
1
gst/base/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
*.gcno
|
|
@ -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
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
Base classes
|
||||
------------
|
||||
|
||||
GstBaseSink
|
||||
FIXME: not much point making it operate in pull mode as a generic
|
||||
base class I guess...
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
||||
|
|
@ -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)
|
||||
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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__ */
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue