summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorThibault Saunier <tsaunier@igalia.com>2021-09-24 16:13:07 -0300
committerThibault Saunier <tsaunier@igalia.com>2021-09-24 16:13:07 -0300
commit6c364d96262f4e39951618c17de85cdd2dc769f3 (patch)
treefb9b22114419dbcb8885fe97e5c6d4a267df7560 /libs
parentb4ca58df7624b005a33e182a511904d7cceea890 (diff)
downloadgstreamer-6c364d96262f4e39951618c17de85cdd2dc769f3.tar.gz
Move files from gstreamer into the "subprojects/gstreamer/" subdir
Diffstat (limited to 'libs')
-rw-r--r--libs/gst/base/README6
-rw-r--r--libs/gst/base/base-prelude.h35
-rw-r--r--libs/gst/base/base.h44
-rw-r--r--libs/gst/base/gstadapter.c1792
-rw-r--r--libs/gst/base/gstadapter.h149
-rw-r--r--libs/gst/base/gstaggregator.c3764
-rw-r--r--libs/gst/base/gstaggregator.h452
-rw-r--r--libs/gst/base/gstbaseparse.c5039
-rw-r--r--libs/gst/base/gstbaseparse.h370
-rw-r--r--libs/gst/base/gstbasesink.c5916
-rw-r--r--libs/gst/base/gstbasesink.h339
-rw-r--r--libs/gst/base/gstbasesrc.c4139
-rw-r--r--libs/gst/base/gstbasesrc.h334
-rw-r--r--libs/gst/base/gstbasetransform.c2921
-rw-r--r--libs/gst/base/gstbasetransform.h372
-rw-r--r--libs/gst/base/gstbitreader-docs.h141
-rw-r--r--libs/gst/base/gstbitreader.c307
-rw-r--r--libs/gst/base/gstbitreader.h328
-rw-r--r--libs/gst/base/gstbitwriter-docs.h92
-rw-r--r--libs/gst/base/gstbitwriter.c449
-rw-r--r--libs/gst/base/gstbitwriter.h384
-rw-r--r--libs/gst/base/gstbytereader-docs.h552
-rw-r--r--libs/gst/base/gstbytereader.c1301
-rw-r--r--libs/gst/base/gstbytereader.h684
-rw-r--r--libs/gst/base/gstbytewriter-docs.h269
-rw-r--r--libs/gst/base/gstbytewriter.c710
-rw-r--r--libs/gst/base/gstbytewriter.h468
-rw-r--r--libs/gst/base/gstcollectpads.c2319
-rw-r--r--libs/gst/base/gstcollectpads.h456
-rw-r--r--libs/gst/base/gstdataqueue.c812
-rw-r--r--libs/gst/base/gstdataqueue.h184
-rw-r--r--libs/gst/base/gstflowcombiner.c355
-rw-r--r--libs/gst/base/gstflowcombiner.h82
-rw-r--r--libs/gst/base/gstindex.c1003
-rw-r--r--libs/gst/base/gstindex.h449
-rw-r--r--libs/gst/base/gstmemindex.c430
-rw-r--r--libs/gst/base/gstpushsrc.c173
-rw-r--r--libs/gst/base/gstpushsrc.h92
-rw-r--r--libs/gst/base/gstqueuearray.c772
-rw-r--r--libs/gst/base/gstqueuearray.h109
-rw-r--r--libs/gst/base/gsttypefindhelper.c832
-rw-r--r--libs/gst/base/gsttypefindhelper.h105
-rw-r--r--libs/gst/base/meson.build107
-rw-r--r--libs/gst/check/check-prelude.h43
-rw-r--r--libs/gst/check/check.h33
-rw-r--r--libs/gst/check/gstbufferstraw.c173
-rw-r--r--libs/gst/check/gstbufferstraw.h40
-rw-r--r--libs/gst/check/gstcheck.c1306
-rw-r--r--libs/gst/check/gstcheck.h756
-rw-r--r--libs/gst/check/gstconsistencychecker.c305
-rw-r--r--libs/gst/check/gstconsistencychecker.h52
-rw-r--r--libs/gst/check/gstharness.c3517
-rw-r--r--libs/gst/check/gstharness.h474
-rw-r--r--libs/gst/check/gsttestclock.c1234
-rw-r--r--libs/gst/check/gsttestclock.h148
-rw-r--r--libs/gst/check/libcheck/README.txt34
-rw-r--r--libs/gst/check/libcheck/check.c642
-rw-r--r--libs/gst/check/libcheck/check.h.in1328
-rw-r--r--libs/gst/check/libcheck/check_error.c79
-rw-r--r--libs/gst/check/libcheck/check_error.h40
-rw-r--r--libs/gst/check/libcheck/check_impl.h141
-rw-r--r--libs/gst/check/libcheck/check_list.c164
-rw-r--r--libs/gst/check/libcheck/check_list.h61
-rw-r--r--libs/gst/check/libcheck/check_log.c548
-rw-r--r--libs/gst/check/libcheck/check_log.h55
-rw-r--r--libs/gst/check/libcheck/check_msg.c315
-rw-r--r--libs/gst/check/libcheck/check_msg.h39
-rw-r--r--libs/gst/check/libcheck/check_pack.c493
-rw-r--r--libs/gst/check/libcheck/check_pack.h84
-rw-r--r--libs/gst/check/libcheck/check_print.c236
-rw-r--r--libs/gst/check/libcheck/check_print.h32
-rw-r--r--libs/gst/check/libcheck/check_run.c801
-rw-r--r--libs/gst/check/libcheck/check_str.c136
-rw-r--r--libs/gst/check/libcheck/check_str.h42
-rw-r--r--libs/gst/check/libcheck/libcompat/alarm.c28
-rw-r--r--libs/gst/check/libcheck/libcompat/clock_gettime.c89
-rw-r--r--libs/gst/check/libcheck/libcompat/getline.c56
-rw-r--r--libs/gst/check/libcheck/libcompat/gettimeofday.c49
-rw-r--r--libs/gst/check/libcheck/libcompat/libcompat.c35
-rw-r--r--libs/gst/check/libcheck/libcompat/libcompat.h237
-rw-r--r--libs/gst/check/libcheck/libcompat/localtime_r.c39
-rw-r--r--libs/gst/check/libcheck/libcompat/strdup.c28
-rw-r--r--libs/gst/check/libcheck/libcompat/strsignal.c30
-rw-r--r--libs/gst/check/libcheck/libcompat/timer_create.c35
-rw-r--r--libs/gst/check/libcheck/libcompat/timer_delete.c53
-rw-r--r--libs/gst/check/libcheck/libcompat/timer_settime.c57
-rw-r--r--libs/gst/check/libcheck/meson.build91
-rw-r--r--libs/gst/check/meson.build88
-rw-r--r--libs/gst/controller/controller-prelude.h35
-rw-r--r--libs/gst/controller/controller.h35
-rw-r--r--libs/gst/controller/gstargbcontrolbinding.c486
-rw-r--r--libs/gst/controller/gstargbcontrolbinding.h103
-rw-r--r--libs/gst/controller/gstdirectcontrolbinding.c553
-rw-r--r--libs/gst/controller/gstdirectcontrolbinding.h129
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsource.c740
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsource.h104
-rw-r--r--libs/gst/controller/gstlfocontrolsource.c594
-rw-r--r--libs/gst/controller/gstlfocontrolsource.h102
-rw-r--r--libs/gst/controller/gstproxycontrolbinding.c200
-rw-r--r--libs/gst/controller/gstproxycontrolbinding.h85
-rw-r--r--libs/gst/controller/gsttimedvaluecontrolsource.c518
-rw-r--r--libs/gst/controller/gsttimedvaluecontrolsource.h160
-rw-r--r--libs/gst/controller/gsttriggercontrolsource.c263
-rw-r--r--libs/gst/controller/gsttriggercontrolsource.h87
-rw-r--r--libs/gst/controller/meson.build82
-rw-r--r--libs/gst/helpers/glib_gobject_helper.py70
-rw-r--r--libs/gst/helpers/gst-completion-helper.c271
-rw-r--r--libs/gst/helpers/gst-plugin-scanner.c71
-rw-r--r--libs/gst/helpers/gst-ptp-helper.c689
-rw-r--r--libs/gst/helpers/gst_gdb.py1277
-rw-r--r--libs/gst/helpers/libgstreamer-gdb.py.in10
-rw-r--r--libs/gst/helpers/meson.build143
-rwxr-xr-xlibs/gst/helpers/ptp_helper_post_install.sh29
-rw-r--r--libs/gst/meson.build10
-rw-r--r--libs/gst/net/gstnet.h31
-rw-r--r--libs/gst/net/gstnetaddressmeta.c141
-rw-r--r--libs/gst/net/gstnetaddressmeta.h63
-rw-r--r--libs/gst/net/gstnetclientclock.c1492
-rw-r--r--libs/gst/net/gstnetclientclock.h106
-rw-r--r--libs/gst/net/gstnetcontrolmessagemeta.c132
-rw-r--r--libs/gst/net/gstnetcontrolmessagemeta.h69
-rw-r--r--libs/gst/net/gstnettimepacket.c247
-rw-r--r--libs/gst/net/gstnettimepacket.h81
-rw-r--r--libs/gst/net/gstnettimeprovider.c477
-rw-r--r--libs/gst/net/gstnettimeprovider.h79
-rw-r--r--libs/gst/net/gstnetutils.c88
-rw-r--r--libs/gst/net/gstnetutils.h37
-rw-r--r--libs/gst/net/gstntppacket.c376
-rw-r--r--libs/gst/net/gstntppacket.h86
-rw-r--r--libs/gst/net/gstptp_private.h19
-rw-r--r--libs/gst/net/gstptpclock.c2660
-rw-r--r--libs/gst/net/gstptpclock.h161
-rw-r--r--libs/gst/net/meson.build69
-rw-r--r--libs/gst/net/net-prelude.h35
-rw-r--r--libs/gst/net/net.h36
-rw-r--r--libs/meson.build1
136 files changed, 0 insertions, 67235 deletions
diff --git a/libs/gst/base/README b/libs/gst/base/README
deleted file mode 100644
index 7214ce2abe..0000000000
--- a/libs/gst/base/README
+++ /dev/null
@@ -1,6 +0,0 @@
-Base classes
-------------
-
-GstBaseSink
- FIXME: not much point making it operate in pull mode as a generic
- base class I guess...
diff --git a/libs/gst/base/base-prelude.h b/libs/gst/base/base-prelude.h
deleted file mode 100644
index 87defde34e..0000000000
--- a/libs/gst/base/base-prelude.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* GStreamer Base Library
- * Copyright (C) 2018 GStreamer developers
- *
- * base-prelude.h: prelude include header for gst-base library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_PRELUDE_H__
-#define __GST_BASE_PRELUDE_H__
-
-#include <gst/gst.h>
-
-#ifndef GST_BASE_API
-#ifdef BUILDING_GST_BASE
-#define GST_BASE_API GST_API_EXPORT /* from config.h */
-#else
-#define GST_BASE_API GST_API_IMPORT
-#endif
-#endif
-
-#endif /* __GST_BASE_PRELUDE_H__ */
diff --git a/libs/gst/base/base.h b/libs/gst/base/base.h
deleted file mode 100644
index 5ad42c11b2..0000000000
--- a/libs/gst/base/base.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* GStreamer
- * Copyright (C) 2012 GStreamer developers
- *
- * base.h: single include header for gst-base library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_H__
-#define __GST_BASE_H__
-
-#include <gst/base/base-prelude.h>
-
-#include <gst/base/gstadapter.h>
-#include <gst/base/gstaggregator.h>
-#include <gst/base/gstbaseparse.h>
-#include <gst/base/gstbasesink.h>
-#include <gst/base/gstbasesrc.h>
-#include <gst/base/gstbasetransform.h>
-#include <gst/base/gstbitreader.h>
-#include <gst/base/gstbitwriter.h>
-#include <gst/base/gstbytereader.h>
-#include <gst/base/gstbytewriter.h>
-#include <gst/base/gstcollectpads.h>
-#include <gst/base/gstdataqueue.h>
-#include <gst/base/gstflowcombiner.h>
-#include <gst/base/gstpushsrc.h>
-#include <gst/base/gstqueuearray.h>
-#include <gst/base/gsttypefindhelper.h>
-
-#endif /* __GST_BASE_H__ */
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
deleted file mode 100644
index 33c84f25a1..0000000000
--- a/libs/gst/base/gstadapter.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstadapter
- * @title: 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.
- *
- * An adapter is created with gst_adapter_new(). It can be freed again with
- * g_object_unref().
- *
- * 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_map()/gst_adapter_unmap()
- * and/or gst_adapter_copy(). After the data has been processed, it is freed
- * using gst_adapter_unmap().
- *
- * Other methods such as gst_adapter_take() and gst_adapter_take_buffer()
- * combine gst_adapter_map() and gst_adapter_unmap() in one method and are
- * potentially more convenient for some use cases.
- *
- * 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:
- * |[<!-- language="C" -->
- * static GstFlowReturn
- * sink_pad_chain (GstPad *pad, GstObject *parent, GstBuffer *buffer)
- * {
- * MyElement *this;
- * GstAdapter *adapter;
- * GstFlowReturn ret = GST_FLOW_OK;
- *
- * this = MY_ELEMENT (parent);
- *
- * 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) {
- * const guint8 *data = gst_adapter_map (adapter, 512);
- * // use flowreturn as an error value
- * ret = my_library_foo (data);
- * gst_adapter_unmap (adapter);
- * gst_adapter_flush (adapter, 512);
- * }
- * return ret;
- * }
- * ]|
- *
- * 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.
- *
- * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might
- * need to clear the adapter after a discontinuity.
- *
- * The adapter will keep track of the timestamps of the buffers
- * that were pushed. The last seen timestamp before the current position
- * can be queried with gst_adapter_prev_pts(). This function can
- * optionally return the number of bytes between the start of the buffer that
- * carried the timestamp and the current adapter position. The distance is
- * useful when dealing with, for example, raw audio samples because it allows
- * you to calculate the timestamp of the current adapter position by using the
- * last seen timestamp and the amount of bytes since. Additionally, the
- * gst_adapter_prev_pts_at_offset() can be used to determine the last
- * seen timestamp at a particular offset in the adapter.
- *
- * The adapter will also keep track of the offset of the buffers
- * (#GST_BUFFER_OFFSET) that were pushed. The last seen offset before the
- * current position can be queried with gst_adapter_prev_offset(). This function
- * can optionally return the number of bytes between the start of the buffer
- * that carried the offset and the current adapter position.
- *
- * Additionally the adapter also keeps track of the PTS, DTS and buffer offset
- * at the last discontinuity, which can be retrieved with
- * gst_adapter_pts_at_discont(), gst_adapter_dts_at_discont() and
- * gst_adapter_offset_at_discont(). The number of bytes that were consumed
- * since then can be queried with gst_adapter_distance_from_discont().
- *
- * A last thing to note is that while #GstAdapter is pretty optimized,
- * merging buffers still might be an operation that requires a `malloc()` and
- * `memcpy()` operation, and these operations are 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. To avoid repeated memory allocations,
- * gst_adapter_copy() can be used to copy data into a (statically allocated)
- * user provided buffer.
- *
- * #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.
- *
- * Note that gst_adapter_push() takes ownership of the buffer passed. Use
- * gst_buffer_ref() before pushing it into the adapter if you still want to
- * access the buffer later. The adapter will never modify the data in the
- * buffer pushed in it.
- */
-
-#include <gst/gst_private.h>
-#include "gstadapter.h"
-#include <string.h>
-#include <gst/base/gstqueuearray.h>
-
-/* default size for the assembled data buffer */
-#define DEFAULT_SIZE 4096
-
-static void gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush);
-
-GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
-#define GST_CAT_DEFAULT gst_adapter_debug
-
-struct _GstAdapter
-{
- GObject object;
-
- /*< private > */
- GstQueueArray *bufqueue;
- gsize size;
- gsize skip;
- guint count;
-
- /* we keep state of assembled pieces */
- gpointer assembled_data;
- gsize assembled_size;
- gsize assembled_len;
-
- GstClockTime pts;
- guint64 pts_distance;
- GstClockTime dts;
- guint64 dts_distance;
- guint64 offset;
- guint64 offset_distance;
-
- gsize scan_offset;
- /* G_MAXUINT when unset */
- guint scan_entry_idx;
-
- GstClockTime pts_at_discont;
- GstClockTime dts_at_discont;
- guint64 offset_at_discont;
-
- guint64 distance_from_discont;
-
- GstMapInfo info;
-};
-
-struct _GstAdapterClass
-{
- GObjectClass parent_class;
-};
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
-#define gst_adapter_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstAdapter, gst_adapter, G_TYPE_OBJECT, _do_init);
-
-static void gst_adapter_dispose (GObject * object);
-static void gst_adapter_finalize (GObject * object);
-
-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)
-{
- adapter->assembled_data = g_malloc (DEFAULT_SIZE);
- adapter->assembled_size = DEFAULT_SIZE;
- adapter->pts = GST_CLOCK_TIME_NONE;
- adapter->pts_distance = 0;
- adapter->dts = GST_CLOCK_TIME_NONE;
- adapter->dts_distance = 0;
- adapter->offset = GST_BUFFER_OFFSET_NONE;
- adapter->offset_distance = 0;
- adapter->pts_at_discont = GST_CLOCK_TIME_NONE;
- adapter->dts_at_discont = GST_CLOCK_TIME_NONE;
- adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE;
- adapter->distance_from_discont = 0;
- adapter->bufqueue = gst_queue_array_new (10);
-}
-
-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_queue_array_free (adapter->bufqueue);
-
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-/**
- * gst_adapter_new:
- *
- * Creates a new #GstAdapter. Free with g_object_unref().
- *
- * Returns: (transfer full): 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)
-{
- GstMiniObject *obj;
- g_return_if_fail (GST_IS_ADAPTER (adapter));
-
- if (adapter->info.memory)
- gst_adapter_unmap (adapter);
-
- while ((obj = gst_queue_array_pop_head (adapter->bufqueue)))
- gst_mini_object_unref (obj);
-
- adapter->count = 0;
- adapter->size = 0;
- adapter->skip = 0;
- adapter->assembled_len = 0;
- adapter->pts = GST_CLOCK_TIME_NONE;
- adapter->pts_distance = 0;
- adapter->dts = GST_CLOCK_TIME_NONE;
- adapter->dts_distance = 0;
- adapter->offset = GST_BUFFER_OFFSET_NONE;
- adapter->offset_distance = 0;
- adapter->pts_at_discont = GST_CLOCK_TIME_NONE;
- adapter->dts_at_discont = GST_CLOCK_TIME_NONE;
- adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE;
- adapter->distance_from_discont = 0;
- adapter->scan_offset = 0;
- adapter->scan_entry_idx = G_MAXUINT;
-}
-
-static inline void
-update_timestamps_and_offset (GstAdapter * adapter, GstBuffer * buf)
-{
- GstClockTime pts, dts;
- guint64 offset;
-
- pts = GST_BUFFER_PTS (buf);
- if (GST_CLOCK_TIME_IS_VALID (pts)) {
- GST_LOG_OBJECT (adapter, "new pts %" GST_TIME_FORMAT, GST_TIME_ARGS (pts));
- adapter->pts = pts;
- adapter->pts_distance = 0;
- }
- dts = GST_BUFFER_DTS (buf);
- if (GST_CLOCK_TIME_IS_VALID (dts)) {
- GST_LOG_OBJECT (adapter, "new dts %" GST_TIME_FORMAT, GST_TIME_ARGS (dts));
- adapter->dts = dts;
- adapter->dts_distance = 0;
- }
- offset = GST_BUFFER_OFFSET (buf);
- if (offset != GST_BUFFER_OFFSET_NONE) {
- GST_LOG_OBJECT (adapter, "new offset %" G_GUINT64_FORMAT, offset);
- adapter->offset = offset;
- adapter->offset_distance = 0;
- }
-
- if (GST_BUFFER_IS_DISCONT (buf)) {
- /* Take values as-is (might be NONE) */
- adapter->pts_at_discont = pts;
- adapter->dts_at_discont = dts;
- adapter->offset_at_discont = offset;
- adapter->distance_from_discont = 0;
- }
-}
-
-/* copy data into @dest, skipping @skip bytes from the head buffers */
-static void
-copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip,
- gsize size)
-{
- GstBuffer *buf;
- gsize bsize, csize;
- guint idx = 0;
-
- /* first step, do skipping */
- /* we might well be copying where we were scanning */
- if (adapter->scan_entry_idx != G_MAXUINT && (adapter->scan_offset <= skip)) {
- idx = adapter->scan_entry_idx;
- skip -= adapter->scan_offset;
- } else {
- idx = 0;
- }
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- bsize = gst_buffer_get_size (buf);
- while (G_UNLIKELY (skip >= bsize)) {
- skip -= bsize;
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- bsize = gst_buffer_get_size (buf);
- }
- /* copy partial buffer */
- csize = MIN (bsize - skip, size);
- GST_DEBUG ("bsize %" G_GSIZE_FORMAT ", skip %" G_GSIZE_FORMAT ", csize %"
- G_GSIZE_FORMAT, bsize, skip, csize);
- GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, "extract %" G_GSIZE_FORMAT
- " bytes", csize);
- gst_buffer_extract (buf, skip, dest, csize);
- size -= csize;
- dest += csize;
-
- /* second step, copy remainder */
- while (size > 0) {
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- bsize = gst_buffer_get_size (buf);
- if (G_LIKELY (bsize > 0)) {
- csize = MIN (bsize, size);
- GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter,
- "extract %" G_GSIZE_FORMAT " bytes", csize);
- gst_buffer_extract (buf, 0, dest, csize);
- size -= csize;
- dest += csize;
- }
- }
-}
-
-/**
- * gst_adapter_push:
- * @adapter: a #GstAdapter
- * @buf: (transfer full): 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)
-{
- gsize size;
-
- g_return_if_fail (GST_IS_ADAPTER (adapter));
- g_return_if_fail (GST_IS_BUFFER (buf));
-
- size = gst_buffer_get_size (buf);
- adapter->size += size;
-
- /* Note: merging buffers at this point is premature. */
- if (gst_queue_array_is_empty (adapter->bufqueue)) {
- GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " bytes",
- buf, size);
- gst_queue_array_push_tail (adapter->bufqueue, buf);
- update_timestamps_and_offset (adapter, buf);
- } else {
- /* Otherwise append to the end, and advance our end pointer */
- GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " bytes at end, "
- "size now %" G_GSIZE_FORMAT, buf, size, adapter->size);
- gst_queue_array_push_tail (adapter->bufqueue, buf);
- }
- ++adapter->count;
-}
-
-#if 0
-/* Internal method only. Tries to merge buffers at the head of the queue
- * to form a single larger buffer of size 'size'.
- *
- * Returns %TRUE if it managed to merge anything.
- */
-static gboolean
-gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size)
-{
- GstBuffer *cur, *head;
- GSList *g;
- gboolean ret = FALSE;
- gsize hsize;
-
- g = adapter->buflist;
- if (g == NULL)
- return FALSE;
-
- head = g->data;
-
- hsize = gst_buffer_get_size (head);
-
- /* Remove skipped part from the buffer (otherwise the buffer might grow indefinitely) */
- head = gst_buffer_make_writable (head);
- gst_buffer_resize (head, adapter->skip, hsize - adapter->skip);
- hsize -= adapter->skip;
- adapter->skip = 0;
- g->data = head;
-
- g = g_slist_next (g);
-
- while (g != NULL && hsize < size) {
- cur = g->data;
- /* Merge the head buffer and the next in line */
- GST_LOG_OBJECT (adapter, "Merging buffers of size %" G_GSIZE_FORMAT " & %"
- G_GSIZE_FORMAT " in search of target %" G_GSIZE_FORMAT,
- hsize, gst_buffer_get_size (cur), size);
-
- head = gst_buffer_append (head, cur);
- hsize = gst_buffer_get_size (head);
- ret = TRUE;
-
- /* Delete the front list item, and store our new buffer in the 2nd list
- * item */
- adapter->buflist = g_slist_delete_link (adapter->buflist, adapter->buflist);
- g->data = head;
-
- /* invalidate scan position */
- adapter->scan_offset = 0;
- adapter->scan_entry = NULL;
-
- g = g_slist_next (g);
- }
-
- return ret;
-}
-#endif
-
-/**
- * gst_adapter_map:
- * @adapter: a #GstAdapter
- * @size: the number of bytes to map/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 memory or the potentially more performant
- * gst_adapter_take_buffer().
- *
- * Returns %NULL if @size bytes are not available.
- *
- * Returns: (transfer none) (array length=size) (element-type guint8) (nullable):
- * a pointer to the first @size bytes of data, or %NULL
- */
-gconstpointer
-gst_adapter_map (GstAdapter * adapter, gsize size)
-{
- GstBuffer *cur;
- gsize skip, csize;
- gsize toreuse, tocopy;
- guint8 *data;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (size > 0, NULL);
-
- if (adapter->info.memory)
- gst_adapter_unmap (adapter);
-
- /* we don't have enough data, return NULL. This is unlikely
- * as one usually does an _available() first instead of peeking a
- * random size. */
- if (G_UNLIKELY (size > adapter->size))
- return NULL;
-
- /* we have enough assembled data, return it */
- if (adapter->assembled_len >= size)
- return adapter->assembled_data;
-
-#if 0
- do {
-#endif
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- skip = adapter->skip;
-
- csize = gst_buffer_get_size (cur);
- if (csize >= size + skip) {
- if (!gst_buffer_map (cur, &adapter->info, GST_MAP_READ))
- return FALSE;
-
- return (guint8 *) adapter->info.data + skip;
- }
- /* We may be able to efficiently merge buffers in our pool to
- * gather a big enough chunk to return it from the head buffer directly */
-#if 0
- } while (gst_adapter_try_to_merge_up (adapter, size));
-#endif
-
- /* see how much data we can reuse from the assembled memory and how much
- * we need to copy */
- toreuse = adapter->assembled_len;
- tocopy = size - toreuse;
-
- /* Gonna need to copy stuff out */
- if (G_UNLIKELY (adapter->assembled_size < size)) {
- adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
- GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %" G_GSIZE_FORMAT,
- adapter->assembled_size);
- if (toreuse == 0) {
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "alloc new buffer");
- /* no g_realloc to avoid a memcpy that is not desired here since we are
- * not going to reuse any data here */
- g_free (adapter->assembled_data);
- adapter->assembled_data = g_malloc (adapter->assembled_size);
- } else {
- /* we are going to reuse all data, realloc then */
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "reusing %" G_GSIZE_FORMAT " bytes",
- toreuse);
- adapter->assembled_data =
- g_realloc (adapter->assembled_data, adapter->assembled_size);
- }
- }
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy remaining %" G_GSIZE_FORMAT
- " bytes from adapter", tocopy);
- data = adapter->assembled_data;
- copy_into_unchecked (adapter, data + toreuse, skip + toreuse, tocopy);
- adapter->assembled_len = size;
-
- return adapter->assembled_data;
-}
-
-/**
- * gst_adapter_unmap:
- * @adapter: a #GstAdapter
- *
- * Releases the memory obtained with the last gst_adapter_map().
- */
-void
-gst_adapter_unmap (GstAdapter * adapter)
-{
- g_return_if_fail (GST_IS_ADAPTER (adapter));
-
- if (adapter->info.memory) {
- GstBuffer *cur = gst_queue_array_peek_head (adapter->bufqueue);
- GST_LOG_OBJECT (adapter, "unmap memory buffer %p", cur);
- gst_buffer_unmap (cur, &adapter->info);
- adapter->info.memory = NULL;
- }
-}
-
-/**
- * gst_adapter_copy: (skip)
- * @adapter: a #GstAdapter
- * @dest: (out caller-allocates) (array length=size) (element-type guint8):
- * the memory to copy into
- * @offset: the bytes offset in the adapter to start from
- * @size: the number of bytes to copy
- *
- * Copies @size bytes of data starting at @offset out of the buffers
- * contained in #GstAdapter into an array @dest provided by the caller.
- *
- * The array @dest should be large enough to contain @size bytes.
- * The user should check that the adapter has (@offset + @size) bytes
- * available before calling this function.
- */
-void
-gst_adapter_copy (GstAdapter * adapter, gpointer dest, gsize offset, gsize size)
-{
- g_return_if_fail (GST_IS_ADAPTER (adapter));
- g_return_if_fail (size > 0);
- g_return_if_fail (offset + size <= adapter->size);
-
- copy_into_unchecked (adapter, dest, offset + adapter->skip, size);
-}
-
-/**
- * gst_adapter_copy_bytes: (rename-to gst_adapter_copy)
- * @adapter: a #GstAdapter
- * @offset: the bytes offset in the adapter to start from
- * @size: the number of bytes to copy
- *
- * Similar to gst_adapter_copy, but more suitable for language bindings. @size
- * bytes of data starting at @offset will be copied out of the buffers contained
- * in @adapter and into a new #GBytes structure which is returned. Depending on
- * the value of the @size argument an empty #GBytes structure may be returned.
- *
- * Returns: (transfer full): A new #GBytes structure containing the copied data.
- *
- * Since: 1.4
- */
-GBytes *
-gst_adapter_copy_bytes (GstAdapter * adapter, gsize offset, gsize size)
-{
- gpointer data;
- data = g_malloc (size);
- gst_adapter_copy (adapter, data, offset, size);
- return g_bytes_new_take (data, size);
-}
-
-/*Flushes the first @flush bytes in the @adapter*/
-static void
-gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
-{
- GstBuffer *cur;
- gsize size;
-
- GST_LOG_OBJECT (adapter, "flushing %" G_GSIZE_FORMAT " bytes", flush);
-
- if (adapter->info.memory)
- gst_adapter_unmap (adapter);
-
- /* clear state */
- adapter->size -= flush;
- adapter->assembled_len = 0;
-
- /* take skip into account */
- flush += adapter->skip;
- /* distance is always at least the amount of skipped bytes */
- adapter->pts_distance -= adapter->skip;
- adapter->dts_distance -= adapter->skip;
- adapter->offset_distance -= adapter->skip;
- adapter->distance_from_discont -= adapter->skip;
-
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- size = gst_buffer_get_size (cur);
- while (flush >= size) {
- /* can skip whole buffer */
- GST_LOG_OBJECT (adapter, "flushing out head buffer");
- adapter->pts_distance += size;
- adapter->dts_distance += size;
- adapter->offset_distance += size;
- adapter->distance_from_discont += size;
- flush -= size;
-
- --adapter->count;
-
- cur = NULL;
- gst_buffer_unref (gst_queue_array_pop_head (adapter->bufqueue));
-
- if (gst_queue_array_is_empty (adapter->bufqueue)) {
- GST_LOG_OBJECT (adapter, "adapter empty now");
- break;
- }
- /* there is a new head buffer, update the timestamps */
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- update_timestamps_and_offset (adapter, cur);
- size = gst_buffer_get_size (cur);
- }
- /* account for the remaining bytes */
- adapter->skip = flush;
- adapter->pts_distance += flush;
- adapter->dts_distance += flush;
- adapter->offset_distance += flush;
- adapter->distance_from_discont += flush;
- /* invalidate scan position */
- adapter->scan_offset = 0;
- adapter->scan_entry_idx = G_MAXUINT;
-}
-
-/**
- * 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_map(), gst_adapter_unmap()
- */
-void
-gst_adapter_flush (GstAdapter * adapter, gsize flush)
-{
- g_return_if_fail (GST_IS_ADAPTER (adapter));
- g_return_if_fail (flush <= adapter->size);
-
- /* flushing out 0 bytes will do nothing */
- if (G_UNLIKELY (flush == 0))
- return;
-
- gst_adapter_flush_unchecked (adapter, flush);
-}
-
-/* internal function, nbytes should be flushed if needed after calling this function */
-static guint8 *
-gst_adapter_get_internal (GstAdapter * adapter, gsize nbytes)
-{
- guint8 *data;
- gsize toreuse, tocopy;
-
- /* see how much data we can reuse from the assembled memory and how much
- * we need to copy */
- toreuse = MIN (nbytes, adapter->assembled_len);
- tocopy = nbytes - toreuse;
-
- /* find memory to return */
- if (adapter->assembled_size >= nbytes && toreuse > 0) {
- /* we reuse already allocated memory but only when we're going to reuse
- * something from it because else we are worse than the malloc and copy
- * case below */
- GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes of assembled"
- " data", toreuse);
- /* we have enough free space in the assembled array */
- data = adapter->assembled_data;
- /* flush after this function should set the assembled_size to 0 */
- adapter->assembled_data = g_malloc (adapter->assembled_size);
- } else {
- GST_LOG_OBJECT (adapter, "allocating %" G_GSIZE_FORMAT " bytes", nbytes);
- /* not enough bytes in the assembled array, just allocate new space */
- data = g_malloc (nbytes);
- /* reuse what we can from the already assembled data */
- if (toreuse) {
- GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes", toreuse);
- GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter,
- "memcpy %" G_GSIZE_FORMAT " bytes", toreuse);
- memcpy (data, adapter->assembled_data, toreuse);
- }
- }
- if (tocopy) {
- /* copy the remaining data */
- copy_into_unchecked (adapter, toreuse + data, toreuse + adapter->skip,
- tocopy);
- }
- return data;
-}
-
-/**
- * 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. The returned bytes will be flushed from the adapter.
- *
- * Caller owns returned value. g_free after usage.
- *
- * Free-function: g_free
- *
- * Returns: (transfer full) (array length=nbytes) (element-type guint8) (nullable):
- * oven-fresh hot data, or %NULL if @nbytes bytes are not available
- */
-gpointer
-gst_adapter_take (GstAdapter * adapter, gsize nbytes)
-{
- gpointer data;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes > 0, NULL);
-
- /* we don't have enough data, return NULL. This is unlikely
- * as one usually does an _available() first instead of peeking a
- * random size. */
- if (G_UNLIKELY (nbytes > adapter->size))
- return NULL;
-
- data = gst_adapter_get_internal (adapter, nbytes);
-
- gst_adapter_flush_unchecked (adapter, nbytes);
-
- return data;
-}
-
-/**
- * gst_adapter_get_buffer_fast:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to get
- *
- * Returns a #GstBuffer containing the first @nbytes of the @adapter, but
- * does not flush them from the adapter. See gst_adapter_take_buffer_fast()
- * for details.
- *
- * Caller owns a reference to the returned buffer. gst_buffer_unref() after
- * usage.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full) (nullable): a #GstBuffer containing the first
- * @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
- * gst_buffer_unref() when no longer needed.
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_adapter_get_buffer_fast (GstAdapter * adapter, gsize nbytes)
-{
- GstBuffer *buffer = NULL;
- GstBuffer *cur;
- gsize skip;
- gsize left = nbytes;
- guint idx, len;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes > 0, NULL);
-
- GST_LOG_OBJECT (adapter, "getting buffer of %" G_GSIZE_FORMAT " bytes",
- nbytes);
-
- /* we don't have enough data, return NULL. This is unlikely
- * as one usually does an _available() first instead of grabbing a
- * random size. */
- if (G_UNLIKELY (nbytes > adapter->size))
- return NULL;
-
- skip = adapter->skip;
- cur = gst_queue_array_peek_head (adapter->bufqueue);
-
- if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
- GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
- " as head buffer", nbytes);
- buffer = gst_buffer_ref (cur);
- goto done;
- }
-
- len = gst_queue_array_get_length (adapter->bufqueue);
-
- for (idx = 0; idx < len && left > 0; idx++) {
- gsize size, cur_size;
-
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx);
- cur_size = gst_buffer_get_size (cur);
- size = MIN (cur_size - skip, left);
-
- GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes"
- " via region copy", size);
- if (buffer)
- gst_buffer_copy_into (buffer, cur,
- GST_BUFFER_COPY_MEMORY | GST_BUFFER_COPY_META, skip, size);
- else
- buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size);
- skip = 0;
- left -= size;
- }
-
-done:
-
- return buffer;
-}
-
-/**
- * gst_adapter_take_buffer_fast:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to take
- *
- * Returns a #GstBuffer containing the first @nbytes of the @adapter.
- * The returned bytes will be flushed from the adapter. This function
- * is potentially more performant than gst_adapter_take_buffer() since
- * it can reuse the memory in pushed buffers by subbuffering or
- * merging. Unlike gst_adapter_take_buffer(), the returned buffer may
- * be composed of multiple non-contiguous #GstMemory objects, no
- * copies are made.
- *
- * Note that no assumptions should be made as to whether certain buffer
- * flags such as the DISCONT flag are set on the returned buffer, or not.
- * The caller needs to explicitly set or unset flags that should be set or
- * unset.
- *
- * This will also copy over all GstMeta of the input buffers except
- * for meta with the %GST_META_FLAG_POOLED flag or with the "memory" tag.
- *
- * This function can return buffer up to the return value of
- * gst_adapter_available() without making copies if possible.
- *
- * Caller owns a reference to the returned buffer. gst_buffer_unref() after
- * usage.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full) (nullable): a #GstBuffer containing the first
- * @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
- * gst_buffer_unref() when no longer needed.
- *
- * Since: 1.2
- */
-GstBuffer *
-gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes)
-{
- GstBuffer *buffer;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes > 0, NULL);
-
- buffer = gst_adapter_get_buffer_fast (adapter, nbytes);
- if (buffer)
- gst_adapter_flush_unchecked (adapter, nbytes);
-
- return buffer;
-}
-
-static gboolean
-foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
-{
- GstBuffer *outbuf = user_data;
- const GstMetaInfo *info = (*meta)->info;
- gboolean do_copy = FALSE;
-
- if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) {
- /* never call the transform_meta with memory specific metadata */
- GST_DEBUG ("not copying memory specific metadata %s",
- g_type_name (info->api));
- do_copy = FALSE;
- } else {
- do_copy = TRUE;
- GST_DEBUG ("copying metadata %s", g_type_name (info->api));
- }
-
- if (do_copy && info->transform_func) {
- GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
- GST_DEBUG ("copy metadata %s", g_type_name (info->api));
- /* simply copy then */
- info->transform_func (outbuf, *meta, inbuf,
- _gst_meta_transform_copy, &copy_data);
- }
- return TRUE;
-}
-
-/**
- * gst_adapter_get_buffer:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to get
- *
- * Returns a #GstBuffer containing the first @nbytes of the @adapter, but
- * does not flush them from the adapter. See gst_adapter_take_buffer()
- * for details.
- *
- * Caller owns a reference to the returned buffer. gst_buffer_unref() after
- * usage.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full) (nullable): a #GstBuffer containing the first
- * @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
- * gst_buffer_unref() when no longer needed.
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_adapter_get_buffer (GstAdapter * adapter, gsize nbytes)
-{
- GstBuffer *buffer;
- GstBuffer *cur;
- gsize hsize, skip;
- guint8 *data;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes > 0, NULL);
-
- GST_LOG_OBJECT (adapter, "getting buffer of %" G_GSIZE_FORMAT " bytes",
- nbytes);
-
- /* we don't have enough data, return NULL. This is unlikely
- * as one usually does an _available() first instead of grabbing a
- * random size. */
- if (G_UNLIKELY (nbytes > adapter->size))
- return NULL;
-
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- skip = adapter->skip;
- hsize = gst_buffer_get_size (cur);
-
- /* our head buffer has enough data left, return it */
- if (skip == 0 && hsize == nbytes) {
- GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
- " as head buffer", nbytes);
- buffer = gst_buffer_ref (cur);
- goto done;
- } else if (hsize >= nbytes + skip) {
- GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
- " via region copy", nbytes);
- buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
- goto done;
- }
-#if 0
- if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
- /* Merged something, let's try again for sub-buffering */
- cur = adapter->buflist->data;
- skip = adapter->skip;
- if (gst_buffer_get_size (cur) >= nbytes + skip) {
- GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
- " via sub-buffer", nbytes);
- buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
- goto done;
- }
- }
-#endif
-
- data = gst_adapter_get_internal (adapter, nbytes);
-
- buffer = gst_buffer_new_wrapped (data, nbytes);
-
- {
- guint idx, len;
- GstBuffer *cur;
- gsize read_offset = 0;
-
- idx = 0;
- len = gst_queue_array_get_length (adapter->bufqueue);
-
- while (idx < len && read_offset < nbytes + adapter->skip) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx);
-
- gst_buffer_foreach_meta (cur, foreach_metadata, buffer);
- read_offset += gst_buffer_get_size (cur);
-
- idx++;
- }
- }
-
-done:
-
- return buffer;
-}
-
-/**
- * gst_adapter_take_buffer:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to take
- *
- * Returns a #GstBuffer containing the first @nbytes bytes of the
- * @adapter. The returned bytes will be flushed from the adapter.
- * This function is potentially more performant than
- * gst_adapter_take() since it can reuse the memory in pushed buffers
- * by subbuffering or merging. This function will always return a
- * buffer with a single memory region.
- *
- * Note that no assumptions should be made as to whether certain buffer
- * flags such as the DISCONT flag are set on the returned buffer, or not.
- * The caller needs to explicitly set or unset flags that should be set or
- * unset.
- *
- * Since 1.6 this will also copy over all GstMeta of the input buffers except
- * for meta with the %GST_META_FLAG_POOLED flag or with the "memory" tag.
- *
- * Caller owns a reference to the returned buffer. gst_buffer_unref() after
- * usage.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full) (nullable): a #GstBuffer containing the first
- * @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
- * gst_buffer_unref() when no longer needed.
- */
-GstBuffer *
-gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes)
-{
- GstBuffer *buffer;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes > 0, NULL);
-
- buffer = gst_adapter_get_buffer (adapter, nbytes);
- if (buffer)
- gst_adapter_flush_unchecked (adapter, nbytes);
-
- return buffer;
-}
-
-/**
- * gst_adapter_take_list:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to take
- *
- * Returns a #GList of buffers containing the first @nbytes bytes of the
- * @adapter. The returned bytes will be flushed from the adapter.
- * When the caller can deal with individual buffers, this function is more
- * performant because no memory should be copied.
- *
- * Caller owns returned list and contained buffers. gst_buffer_unref() each
- * buffer in the list before freeing the list after usage.
- *
- * Returns: (element-type Gst.Buffer) (transfer full) (nullable): a #GList of
- * buffers containing the first @nbytes of the adapter, or %NULL if @nbytes
- * bytes are not available
- */
-GList *
-gst_adapter_take_list (GstAdapter * adapter, gsize nbytes)
-{
- GQueue queue = G_QUEUE_INIT;
- GstBuffer *cur;
- gsize hsize, skip, cur_size;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes <= adapter->size, NULL);
-
- GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes);
-
- while (nbytes > 0) {
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- skip = adapter->skip;
- cur_size = gst_buffer_get_size (cur);
- hsize = MIN (nbytes, cur_size - skip);
-
- cur = gst_adapter_take_buffer (adapter, hsize);
-
- g_queue_push_tail (&queue, cur);
-
- nbytes -= hsize;
- }
- return queue.head;
-}
-
-/**
- * gst_adapter_get_list:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to get
- *
- * Returns a #GList of buffers containing the first @nbytes bytes of the
- * @adapter, but does not flush them from the adapter. See
- * gst_adapter_take_list() for details.
- *
- * Caller owns returned list and contained buffers. gst_buffer_unref() each
- * buffer in the list before freeing the list after usage.
- *
- * Returns: (element-type Gst.Buffer) (transfer full) (nullable): a #GList of
- * buffers containing the first @nbytes of the adapter, or %NULL if @nbytes
- * bytes are not available
- *
- * Since: 1.6
- */
-GList *
-gst_adapter_get_list (GstAdapter * adapter, gsize nbytes)
-{
- GQueue queue = G_QUEUE_INIT;
- GstBuffer *cur, *buffer;
- gsize hsize, skip, cur_size;
- guint idx;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
- g_return_val_if_fail (nbytes <= adapter->size, NULL);
-
- GST_LOG_OBJECT (adapter, "getting %" G_GSIZE_FORMAT " bytes", nbytes);
-
- idx = 0;
- skip = adapter->skip;
-
- while (nbytes > 0) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- cur_size = gst_buffer_get_size (cur);
- hsize = MIN (nbytes, cur_size - skip);
-
- if (skip == 0 && cur_size == hsize) {
- GST_LOG_OBJECT (adapter,
- "inserting a buffer of %" G_GSIZE_FORMAT " bytes", hsize);
- buffer = gst_buffer_ref (cur);
- } else {
- GST_LOG_OBJECT (adapter, "inserting a buffer of %" G_GSIZE_FORMAT " bytes"
- " via region copy", hsize);
- buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, hsize);
- }
-
- g_queue_push_tail (&queue, buffer);
-
- nbytes -= hsize;
- skip = 0;
- }
-
- return queue.head;
-}
-
-/**
- * gst_adapter_take_buffer_list:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to take
- *
- * Returns a #GstBufferList of buffers containing the first @nbytes bytes of
- * the @adapter. The returned bytes will be flushed from the adapter.
- * When the caller can deal with individual buffers, this function is more
- * performant because no memory should be copied.
- *
- * Caller owns the returned list. Call gst_buffer_list_unref() to free
- * the list after usage.
- *
- * Returns: (transfer full) (nullable): a #GstBufferList of buffers containing
- * the first @nbytes of the adapter, or %NULL if @nbytes bytes are not
- * available
- *
- * Since: 1.6
- */
-GstBufferList *
-gst_adapter_take_buffer_list (GstAdapter * adapter, gsize nbytes)
-{
- GstBufferList *buffer_list;
- GstBuffer *cur;
- gsize hsize, skip, cur_size;
- guint n_bufs;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
-
- if (nbytes > adapter->size)
- return NULL;
-
- GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes);
-
- /* try to create buffer list with sufficient size, so no resize is done later */
- if (adapter->count < 64)
- n_bufs = adapter->count;
- else
- n_bufs = (adapter->count * nbytes * 1.2 / adapter->size) + 1;
-
- buffer_list = gst_buffer_list_new_sized (n_bufs);
-
- while (nbytes > 0) {
- cur = gst_queue_array_peek_head (adapter->bufqueue);
- skip = adapter->skip;
- cur_size = gst_buffer_get_size (cur);
- hsize = MIN (nbytes, cur_size - skip);
-
- gst_buffer_list_add (buffer_list, gst_adapter_take_buffer (adapter, hsize));
- nbytes -= hsize;
- }
- return buffer_list;
-}
-
-/**
- * gst_adapter_get_buffer_list:
- * @adapter: a #GstAdapter
- * @nbytes: the number of bytes to get
- *
- * Returns a #GstBufferList of buffers containing the first @nbytes bytes of
- * the @adapter but does not flush them from the adapter. See
- * gst_adapter_take_buffer_list() for details.
- *
- * Caller owns the returned list. Call gst_buffer_list_unref() to free
- * the list after usage.
- *
- * Returns: (transfer full) (nullable): a #GstBufferList of buffers containing
- * the first @nbytes of the adapter, or %NULL if @nbytes bytes are not
- * available
- *
- * Since: 1.6
- */
-GstBufferList *
-gst_adapter_get_buffer_list (GstAdapter * adapter, gsize nbytes)
-{
- GstBufferList *buffer_list;
- GstBuffer *cur, *buffer;
- gsize hsize, skip, cur_size;
- guint n_bufs;
- guint idx;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
-
- if (nbytes > adapter->size)
- return NULL;
-
- GST_LOG_OBJECT (adapter, "getting %" G_GSIZE_FORMAT " bytes", nbytes);
-
- /* try to create buffer list with sufficient size, so no resize is done later */
- if (adapter->count < 64)
- n_bufs = adapter->count;
- else
- n_bufs = (adapter->count * nbytes * 1.2 / adapter->size) + 1;
-
- buffer_list = gst_buffer_list_new_sized (n_bufs);
-
- idx = 0;
- skip = adapter->skip;
-
- while (nbytes > 0) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- cur_size = gst_buffer_get_size (cur);
- hsize = MIN (nbytes, cur_size - skip);
-
- if (skip == 0 && cur_size == hsize) {
- GST_LOG_OBJECT (adapter,
- "inserting a buffer of %" G_GSIZE_FORMAT " bytes", hsize);
- buffer = gst_buffer_ref (cur);
- } else {
- GST_LOG_OBJECT (adapter, "inserting a buffer of %" G_GSIZE_FORMAT " bytes"
- " via region copy", hsize);
- buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, hsize);
- }
-
- gst_buffer_list_add (buffer_list, buffer);
-
- nbytes -= hsize;
- skip = 0;
- }
-
- return buffer_list;
-}
-
-/**
- * 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_map() without that function
- * returning %NULL.
- *
- * Returns: number of bytes available in @adapter
- */
-gsize
-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 that are immediately available without
- * requiring any expensive operations (like copying the data into a
- * temporary buffer).
- *
- * Returns: number of bytes that are available in @adapter without expensive
- * operations
- */
-gsize
-gst_adapter_available_fast (GstAdapter * adapter)
-{
- GstBuffer *cur;
- gsize size;
- guint idx;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
-
- /* no data */
- if (adapter->size == 0)
- return 0;
-
- /* some stuff we already assembled */
- if (adapter->assembled_len)
- return adapter->assembled_len;
-
- /* take the first non-zero buffer */
- idx = 0;
- while (TRUE) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- size = gst_buffer_get_size (cur);
- if (size != 0)
- break;
- }
-
- /* we can quickly get the (remaining) data of the first buffer */
- return size - adapter->skip;
-}
-
-/**
- * gst_adapter_distance_from_discont:
- * @adapter: a #GstAdapter
- *
- * Get the distance in bytes since the last buffer with the
- * %GST_BUFFER_FLAG_DISCONT flag.
- *
- * The distance will be reset to 0 for all buffers with
- * %GST_BUFFER_FLAG_DISCONT on them, and then calculated for all other
- * following buffers based on their size.
- *
- * Since: 1.10
- *
- * Returns: The offset. Can be %GST_BUFFER_OFFSET_NONE.
- */
-guint64
-gst_adapter_distance_from_discont (GstAdapter * adapter)
-{
- return adapter->distance_from_discont;
-}
-
-/**
- * gst_adapter_offset_at_discont:
- * @adapter: a #GstAdapter
- *
- * Get the offset that was on the last buffer with the GST_BUFFER_FLAG_DISCONT
- * flag, or GST_BUFFER_OFFSET_NONE.
- *
- * Since: 1.10
- *
- * Returns: The offset at the last discont or GST_BUFFER_OFFSET_NONE.
- */
-guint64
-gst_adapter_offset_at_discont (GstAdapter * adapter)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_BUFFER_OFFSET_NONE);
-
- return adapter->offset_at_discont;
-}
-
-/**
- * gst_adapter_pts_at_discont:
- * @adapter: a #GstAdapter
- *
- * Get the PTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT
- * flag, or GST_CLOCK_TIME_NONE.
- *
- * Since: 1.10
- *
- * Returns: The PTS at the last discont or GST_CLOCK_TIME_NONE.
- */
-GstClockTime
-gst_adapter_pts_at_discont (GstAdapter * adapter)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- return adapter->pts_at_discont;
-}
-
-/**
- * gst_adapter_dts_at_discont:
- * @adapter: a #GstAdapter
- *
- * Get the DTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT
- * flag, or GST_CLOCK_TIME_NONE.
- *
- * Since: 1.10
- *
- * Returns: The DTS at the last discont or GST_CLOCK_TIME_NONE.
- */
-GstClockTime
-gst_adapter_dts_at_discont (GstAdapter * adapter)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- return adapter->dts_at_discont;
-}
-
-/**
- * gst_adapter_prev_offset:
- * @adapter: a #GstAdapter
- * @distance: (out) (allow-none): pointer to a location for distance, or %NULL
- *
- * Get the offset that was before the current byte in the adapter. When
- * @distance is given, the amount of bytes between the offset and the current
- * position is returned.
- *
- * The offset is reset to GST_BUFFER_OFFSET_NONE and the distance is set to 0
- * when the adapter is first created or when it is cleared. This also means that
- * before the first byte with an offset is removed from the adapter, the offset
- * and distance returned are GST_BUFFER_OFFSET_NONE and 0 respectively.
- *
- * Since: 1.10
- *
- * Returns: The previous seen offset.
- */
-guint64
-gst_adapter_prev_offset (GstAdapter * adapter, guint64 * distance)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_BUFFER_OFFSET_NONE);
-
- if (distance)
- *distance = adapter->offset_distance;
-
- return adapter->offset;
-}
-
-/**
- * gst_adapter_prev_pts:
- * @adapter: a #GstAdapter
- * @distance: (out) (allow-none): pointer to location for distance, or %NULL
- *
- * Get the pts that was before the current byte in the adapter. When
- * @distance is given, the amount of bytes between the pts and the current
- * position is returned.
- *
- * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
- * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a pts is removed from the adapter, the pts
- * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
- *
- * Returns: The previously seen pts.
- */
-GstClockTime
-gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- if (distance)
- *distance = adapter->pts_distance;
-
- return adapter->pts;
-}
-
-/**
- * gst_adapter_prev_dts:
- * @adapter: a #GstAdapter
- * @distance: (out) (allow-none): pointer to location for distance, or %NULL
- *
- * Get the dts that was before the current byte in the adapter. When
- * @distance is given, the amount of bytes between the dts and the current
- * position is returned.
- *
- * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
- * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a dts is removed from the adapter, the dts
- * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
- *
- * Returns: The previously seen dts.
- */
-GstClockTime
-gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
-{
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- if (distance)
- *distance = adapter->dts_distance;
-
- return adapter->dts;
-}
-
-/**
- * gst_adapter_prev_pts_at_offset:
- * @adapter: a #GstAdapter
- * @offset: the offset in the adapter at which to get timestamp
- * @distance: (out) (allow-none): pointer to location for distance, or %NULL
- *
- * Get the pts that was before the byte at offset @offset in the adapter. When
- * @distance is given, the amount of bytes between the pts and the current
- * position is returned.
- *
- * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
- * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a pts is removed from the adapter, the pts
- * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
- *
- * Since: 1.2
- * Returns: The previously seen pts at given offset.
- */
-GstClockTime
-gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
- guint64 * distance)
-{
- GstBuffer *cur;
- gsize read_offset = 0;
- gsize pts_offset = 0;
- GstClockTime pts = adapter->pts;
- guint idx, len;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- idx = 0;
- len = gst_queue_array_get_length (adapter->bufqueue);
-
- while (idx < len && read_offset < offset + adapter->skip) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
-
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (cur))) {
- pts = GST_BUFFER_PTS (cur);
- pts_offset = read_offset;
- }
-
- read_offset += gst_buffer_get_size (cur);
- }
-
- if (distance)
- *distance = adapter->pts_distance + offset - pts_offset;
-
- return pts;
-}
-
-/**
- * gst_adapter_prev_dts_at_offset:
- * @adapter: a #GstAdapter
- * @offset: the offset in the adapter at which to get timestamp
- * @distance: (out) (allow-none): pointer to location for distance, or %NULL
- *
- * Get the dts that was before the byte at offset @offset in the adapter. When
- * @distance is given, the amount of bytes between the dts and the current
- * position is returned.
- *
- * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
- * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a dts is removed from the adapter, the dts
- * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
- *
- * Since: 1.2
- * Returns: The previously seen dts at given offset.
- */
-GstClockTime
-gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset,
- guint64 * distance)
-{
- GstBuffer *cur;
- gsize read_offset = 0;
- gsize dts_offset = 0;
- GstClockTime dts = adapter->dts;
- guint idx, len;
-
- g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
- idx = 0;
- len = gst_queue_array_get_length (adapter->bufqueue);
-
- while (idx < len && read_offset < offset + adapter->skip) {
- cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
-
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cur))) {
- dts = GST_BUFFER_DTS (cur);
- dts_offset = read_offset;
- }
-
- read_offset += gst_buffer_get_size (cur);
- }
-
- if (distance)
- *distance = adapter->dts_distance + offset - dts_offset;
-
- return dts;
-}
-
-/**
- * gst_adapter_masked_scan_uint32_peek:
- * @adapter: a #GstAdapter
- * @mask: mask to apply to data before matching against @pattern
- * @pattern: pattern to match (after mask is applied)
- * @offset: offset into the adapter data from which to start scanning, returns
- * the last scanned position.
- * @size: number of bytes to scan from offset
- * @value: (out) (allow-none): pointer to uint32 to return matching data
- *
- * Scan for pattern @pattern with applied mask @mask in the adapter data,
- * starting from offset @offset. If a match is found, the value that matched
- * is returned through @value, otherwise @value is left untouched.
- *
- * The bytes in @pattern and @mask are interpreted left-to-right, regardless
- * of endianness. All four bytes of the pattern must be present in the
- * adapter for it to match, even if the first or last bytes are masked out.
- *
- * It is an error to call this function without making sure that there is
- * enough data (offset+size bytes) in the adapter.
- *
- * Returns: offset of the first match, or -1 if no match was found.
- */
-gssize
-gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
- guint32 pattern, gsize offset, gsize size, guint32 * value)
-{
- gsize skip, bsize, i;
- guint32 state;
- GstMapInfo info;
- guint8 *bdata;
- GstBuffer *buf;
- guint idx;
-
- g_return_val_if_fail (size > 0, -1);
- g_return_val_if_fail (offset + size <= adapter->size, -1);
- g_return_val_if_fail (((~mask) & pattern) == 0, -1);
-
- /* we can't find the pattern with less than 4 bytes */
- if (G_UNLIKELY (size < 4))
- return -1;
-
- skip = offset + adapter->skip;
-
- /* first step, do skipping and position on the first buffer */
- /* optimistically assume scanning continues sequentially */
- if (adapter->scan_entry_idx != G_MAXUINT && (adapter->scan_offset <= skip)) {
- idx = adapter->scan_entry_idx;
- skip -= adapter->scan_offset;
- } else {
- idx = 0;
- adapter->scan_offset = 0;
- adapter->scan_entry_idx = G_MAXUINT;
- }
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- bsize = gst_buffer_get_size (buf);
- while (G_UNLIKELY (skip >= bsize)) {
- skip -= bsize;
- adapter->scan_offset += bsize;
- adapter->scan_entry_idx = idx;
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
- bsize = gst_buffer_get_size (buf);
- }
- /* get the data now */
- if (!gst_buffer_map (buf, &info, GST_MAP_READ))
- return -1;
-
- bdata = (guint8 *) info.data + skip;
- bsize = info.size - skip;
- skip = 0;
-
- /* set the state to something that does not match */
- state = ~pattern;
-
- /* now find data */
- do {
- bsize = MIN (bsize, size);
- for (i = 0; i < bsize; i++) {
- state = ((state << 8) | bdata[i]);
- if (G_UNLIKELY ((state & mask) == pattern)) {
- /* we have a match but we need to have skipped at
- * least 4 bytes to fill the state. */
- if (G_LIKELY (skip + i >= 3)) {
- if (G_LIKELY (value))
- *value = state;
- gst_buffer_unmap (buf, &info);
- return offset + skip + i - 3;
- }
- }
- }
- size -= bsize;
- if (size == 0)
- break;
-
- /* nothing found yet, go to next buffer */
- skip += bsize;
- adapter->scan_offset += info.size;
- adapter->scan_entry_idx = idx;
- gst_buffer_unmap (buf, &info);
- buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
-
- if (!gst_buffer_map (buf, &info, GST_MAP_READ))
- return -1;
-
- bsize = info.size;
- bdata = info.data;
- } while (TRUE);
-
- gst_buffer_unmap (buf, &info);
-
- /* nothing found */
- return -1;
-}
-
-/**
- * gst_adapter_masked_scan_uint32:
- * @adapter: a #GstAdapter
- * @mask: mask to apply to data before matching against @pattern
- * @pattern: pattern to match (after mask is applied)
- * @offset: offset into the adapter data from which to start scanning, returns
- * the last scanned position.
- * @size: number of bytes to scan from offset
- *
- * Scan for pattern @pattern with applied mask @mask in the adapter data,
- * starting from offset @offset.
- *
- * The bytes in @pattern and @mask are interpreted left-to-right, regardless
- * of endianness. All four bytes of the pattern must be present in the
- * adapter for it to match, even if the first or last bytes are masked out.
- *
- * It is an error to call this function without making sure that there is
- * enough data (offset+size bytes) in the adapter.
- *
- * This function calls gst_adapter_masked_scan_uint32_peek() passing %NULL
- * for value.
- *
- * Returns: offset of the first match, or -1 if no match was found.
- *
- * Example:
- * |[
- * // Assume the adapter contains 0x00 0x01 0x02 ... 0xfe 0xff
- *
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 256);
- * // -> returns 0
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 1, 255);
- * // -> returns -1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 255);
- * // -> returns 1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0001, 0, 256);
- * // -> returns -1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0203, 0, 256);
- * // -> returns 0
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 256);
- * // -> returns 2
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 4);
- * // -> returns -1
- * ]|
- */
-gssize
-gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
- guint32 pattern, gsize offset, gsize size)
-{
- return gst_adapter_masked_scan_uint32_peek (adapter, mask, pattern, offset,
- size, NULL);
-}
diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h
deleted file mode 100644
index 3945085a49..0000000000
--- a/libs/gst/base/gstadapter.h
+++ /dev/null
@@ -1,149 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <gst/gst.h>
-
-#ifndef __GST_ADAPTER_H__
-#define __GST_ADAPTER_H__
-
-#include <gst/base/base-prelude.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(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ADAPTER))
-
-/**
- * GstAdapter:
- *
- * The opaque #GstAdapter data structure.
- */
-typedef struct _GstAdapter GstAdapter;
-typedef struct _GstAdapterClass GstAdapterClass;
-
-GST_BASE_API
-GType gst_adapter_get_type (void);
-
-GST_BASE_API
-GstAdapter * gst_adapter_new (void) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_adapter_clear (GstAdapter *adapter);
-
-GST_BASE_API
-void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf);
-
-GST_BASE_API
-gconstpointer gst_adapter_map (GstAdapter *adapter, gsize size);
-
-GST_BASE_API
-void gst_adapter_unmap (GstAdapter *adapter);
-
-GST_BASE_API
-void gst_adapter_copy (GstAdapter *adapter, gpointer dest,
- gsize offset, gsize size);
-GST_BASE_API
-GBytes * gst_adapter_copy_bytes (GstAdapter *adapter,
- gsize offset, gsize size);
-GST_BASE_API
-void gst_adapter_flush (GstAdapter *adapter, gsize flush);
-
-GST_BASE_API
-gpointer gst_adapter_take (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GList* gst_adapter_take_list (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBuffer * gst_adapter_take_buffer_fast (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBufferList * gst_adapter_take_buffer_list (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBuffer* gst_adapter_get_buffer (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GList* gst_adapter_get_list (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBuffer * gst_adapter_get_buffer_fast (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-GstBufferList * gst_adapter_get_buffer_list (GstAdapter *adapter, gsize nbytes);
-
-GST_BASE_API
-gsize gst_adapter_available (GstAdapter *adapter);
-
-GST_BASE_API
-gsize gst_adapter_available_fast (GstAdapter *adapter);
-
-GST_BASE_API
-GstClockTime gst_adapter_prev_pts (GstAdapter *adapter, guint64 *distance);
-
-GST_BASE_API
-GstClockTime gst_adapter_prev_dts (GstAdapter *adapter, guint64 *distance);
-
-GST_BASE_API
-GstClockTime gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance);
-
-GST_BASE_API
-GstClockTime gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance);
-
-GST_BASE_API
-guint64 gst_adapter_prev_offset (GstAdapter *adapter, guint64 *distance);
-
-GST_BASE_API
-GstClockTime gst_adapter_pts_at_discont (GstAdapter *adapter);
-
-GST_BASE_API
-GstClockTime gst_adapter_dts_at_discont (GstAdapter *adapter);
-
-GST_BASE_API
-guint64 gst_adapter_offset_at_discont (GstAdapter *adapter);
-
-GST_BASE_API
-guint64 gst_adapter_distance_from_discont (GstAdapter *adapter);
-
-GST_BASE_API
-gssize gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
- guint32 pattern, gsize offset, gsize size);
-GST_BASE_API
-gssize gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
- guint32 pattern, gsize offset, gsize size, guint32 * value);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAdapter, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_ADAPTER_H__ */
diff --git a/libs/gst/base/gstaggregator.c b/libs/gst/base/gstaggregator.c
deleted file mode 100644
index 5a6e30f42d..0000000000
--- a/libs/gst/base/gstaggregator.c
+++ /dev/null
@@ -1,3764 +0,0 @@
-/* GStreamer aggregator base class
- * Copyright (C) 2014 Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
- * Copyright (C) 2014 Thibault Saunier <tsaunier@gnome.org>
- *
- * gstaggregator.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION: gstaggregator
- * @title: GstAggregator
- * @short_description: Base class for mixers and muxers, manages a set of input
- * pads and aggregates their streams
- * @see_also: gstcollectpads for historical reasons.
- *
- * Manages a set of pads with the purpose of aggregating their buffers.
- * Control is given to the subclass when all pads have data.
- *
- * * Base class for mixers and muxers. Subclasses should at least implement
- * the #GstAggregatorClass::aggregate virtual method.
- *
- * * Installs a #GstPadChainFunction, a #GstPadEventFullFunction and a
- * #GstPadQueryFunction to queue all serialized data packets per sink pad.
- * Subclasses should not overwrite those, but instead implement
- * #GstAggregatorClass::sink_event and #GstAggregatorClass::sink_query as
- * needed.
- *
- * * When data is queued on all pads, the aggregate vmethod is called.
- *
- * * One can peek at the data on any given GstAggregatorPad with the
- * gst_aggregator_pad_peek_buffer() method, and remove it from the pad
- * with the gst_aggregator_pad_pop_buffer () method. When a buffer
- * has been taken with pop_buffer (), a new buffer can be queued
- * on that pad.
- *
- * * When gst_aggregator_pad_peek_buffer() or gst_aggregator_pad_has_buffer()
- * are called, a reference is taken to the returned buffer, which stays
- * valid until either:
- *
- * - gst_aggregator_pad_pop_buffer() is called, in which case the caller
- * is guaranteed that the buffer they receive is the same as the peeked
- * buffer.
- * - gst_aggregator_pad_drop_buffer() is called, in which case the caller
- * is guaranteed that the dropped buffer is the one that was peeked.
- * - the subclass implementation of #GstAggregatorClass.aggregate returns.
- *
- * Subsequent calls to gst_aggregator_pad_peek_buffer() or
- * gst_aggregator_pad_has_buffer() return / check the same buffer that was
- * returned / checked, until one of the conditions listed above is met.
- *
- * Subclasses are only allowed to call these methods from the aggregate
- * thread.
- *
- * * If the subclass wishes to push a buffer downstream in its aggregate
- * implementation, it should do so through the
- * gst_aggregator_finish_buffer() method. This method will take care
- * of sending and ordering mandatory events such as stream start, caps
- * and segment. Buffer lists can also be pushed out with
- * gst_aggregator_finish_buffer_list().
- *
- * * Same goes for EOS events, which should not be pushed directly by the
- * subclass, it should instead return GST_FLOW_EOS in its aggregate
- * implementation.
- *
- * * Note that the aggregator logic regarding gap event handling is to turn
- * these into gap buffers with matching PTS and duration. It will also
- * flag these buffers with GST_BUFFER_FLAG_GAP and GST_BUFFER_FLAG_DROPPABLE
- * to ease their identification and subsequent processing.
- *
- * * Subclasses must use (a subclass of) #GstAggregatorPad for both their
- * sink and source pads.
- * See gst_element_class_add_static_pad_template_with_gtype().
- *
- * This class used to live in gst-plugins-bad and was moved to core.
- *
- * Since: 1.14
- */
-
-/**
- * SECTION: gstaggregatorpad
- * @title: GstAggregatorPad
- * @short_description: #GstPad subclass for pads managed by #GstAggregator
- * @see_also: gstcollectpads for historical reasons.
- *
- * Pads managed by a #GstAggregator subclass.
- *
- * This class used to live in gst-plugins-bad and was moved to core.
- *
- * Since: 1.14
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string.h> /* strlen */
-
-#include "gstaggregator.h"
-
-GType
-gst_aggregator_start_time_selection_get_type (void)
-{
- static GType gtype = 0;
-
- if (g_once_init_enter (&gtype)) {
- static const GEnumValue values[] = {
- {GST_AGGREGATOR_START_TIME_SELECTION_ZERO,
- "GST_AGGREGATOR_START_TIME_SELECTION_ZERO", "zero"},
- {GST_AGGREGATOR_START_TIME_SELECTION_FIRST,
- "GST_AGGREGATOR_START_TIME_SELECTION_FIRST", "first"},
- {GST_AGGREGATOR_START_TIME_SELECTION_SET,
- "GST_AGGREGATOR_START_TIME_SELECTION_SET", "set"},
- {0, NULL, NULL}
- };
- GType new_type =
- g_enum_register_static ("GstAggregatorStartTimeSelection", values);
-
- g_once_init_leave (&gtype, new_type);
- }
- return gtype;
-}
-
-/* Might become API */
-#if 0
-static void gst_aggregator_merge_tags (GstAggregator * aggregator,
- const GstTagList * tags, GstTagMergeMode mode);
-#endif
-static void gst_aggregator_set_latency_property (GstAggregator * agg,
- GstClockTime latency);
-static GstClockTime gst_aggregator_get_latency_property (GstAggregator * agg);
-
-static GstClockTime gst_aggregator_get_latency_unlocked (GstAggregator * self);
-
-static void gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad,
- GstBuffer * buffer, gboolean dequeued);
-
-GST_DEBUG_CATEGORY_STATIC (aggregator_debug);
-#define GST_CAT_DEFAULT aggregator_debug
-
-/* Locking order, locks in this element must always be taken in this order
- *
- * standard sink pad stream lock -> GST_PAD_STREAM_LOCK (aggpad)
- * Aggregator pad flush lock -> PAD_FLUSH_LOCK(aggpad)
- * standard src pad stream lock -> GST_PAD_STREAM_LOCK (srcpad)
- * Aggregator src lock -> SRC_LOCK(agg) w/ SRC_WAIT/BROADCAST
- * standard element object lock -> GST_OBJECT_LOCK(agg)
- * Aggregator pad lock -> PAD_LOCK (aggpad) w/ PAD_WAIT/BROADCAST_EVENT(aggpad)
- * standard src pad object lock -> GST_OBJECT_LOCK(srcpad)
- * standard sink pad object lock -> GST_OBJECT_LOCK(aggpad)
- */
-
-/* GstAggregatorPad definitions */
-#define PAD_LOCK(pad) G_STMT_START { \
- GST_TRACE_OBJECT (pad, "Taking PAD lock from thread %p", \
- g_thread_self()); \
- g_mutex_lock(&pad->priv->lock); \
- GST_TRACE_OBJECT (pad, "Took PAD lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define PAD_UNLOCK(pad) G_STMT_START { \
- GST_TRACE_OBJECT (pad, "Releasing PAD lock from thread %p", \
- g_thread_self()); \
- g_mutex_unlock(&pad->priv->lock); \
- GST_TRACE_OBJECT (pad, "Release PAD lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-
-#define PAD_WAIT_EVENT(pad) G_STMT_START { \
- GST_LOG_OBJECT (pad, "Waiting for buffer to be consumed thread %p", \
- g_thread_self()); \
- g_cond_wait(&(((GstAggregatorPad* )pad)->priv->event_cond), \
- (&((GstAggregatorPad*)pad)->priv->lock)); \
- GST_LOG_OBJECT (pad, "DONE Waiting for buffer to be consumed on thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define PAD_BROADCAST_EVENT(pad) G_STMT_START { \
- GST_LOG_OBJECT (pad, "Signaling buffer consumed from thread %p", \
- g_thread_self()); \
- g_cond_broadcast(&(((GstAggregatorPad* )pad)->priv->event_cond)); \
- } G_STMT_END
-
-
-#define PAD_FLUSH_LOCK(pad) G_STMT_START { \
- GST_TRACE_OBJECT (pad, "Taking lock from thread %p", \
- g_thread_self()); \
- g_mutex_lock(&pad->priv->flush_lock); \
- GST_TRACE_OBJECT (pad, "Took lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define PAD_FLUSH_UNLOCK(pad) G_STMT_START { \
- GST_TRACE_OBJECT (pad, "Releasing lock from thread %p", \
- g_thread_self()); \
- g_mutex_unlock(&pad->priv->flush_lock); \
- GST_TRACE_OBJECT (pad, "Release lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define SRC_LOCK(self) G_STMT_START { \
- GST_TRACE_OBJECT (self, "Taking src lock from thread %p", \
- g_thread_self()); \
- g_mutex_lock(&self->priv->src_lock); \
- GST_TRACE_OBJECT (self, "Took src lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define SRC_UNLOCK(self) G_STMT_START { \
- GST_TRACE_OBJECT (self, "Releasing src lock from thread %p", \
- g_thread_self()); \
- g_mutex_unlock(&self->priv->src_lock); \
- GST_TRACE_OBJECT (self, "Released src lock from thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define SRC_WAIT(self) G_STMT_START { \
- GST_LOG_OBJECT (self, "Waiting for src on thread %p", \
- g_thread_self()); \
- g_cond_wait(&(self->priv->src_cond), &(self->priv->src_lock)); \
- GST_LOG_OBJECT (self, "DONE Waiting for src on thread %p", \
- g_thread_self()); \
- } G_STMT_END
-
-#define SRC_BROADCAST(self) G_STMT_START { \
- GST_LOG_OBJECT (self, "Signaling src from thread %p", \
- g_thread_self()); \
- if (self->priv->aggregate_id) \
- gst_clock_id_unschedule (self->priv->aggregate_id); \
- g_cond_broadcast(&(self->priv->src_cond)); \
- } G_STMT_END
-
-struct _GstAggregatorPadPrivate
-{
- /* Following fields are protected by the PAD_LOCK */
- GstFlowReturn flow_return;
-
- guint32 last_flush_start_seqnum;
- guint32 last_flush_stop_seqnum;
-
- gboolean first_buffer;
-
- GQueue data; /* buffers, events and queries */
- GstBuffer *clipped_buffer;
- guint num_buffers;
- GstBuffer *peeked_buffer;
-
- /* used to track fill state of queues, only used with live-src and when
- * latency property is set to > 0 */
- GstClockTime head_position;
- GstClockTime tail_position;
- GstClockTime head_time; /* running time */
- GstClockTime tail_time;
- GstClockTime time_level; /* how much head is ahead of tail */
- GstSegment head_segment; /* segment before the queue */
-
- gboolean negotiated;
-
- gboolean eos;
-
- GMutex lock;
- GCond event_cond;
- /* This lock prevents a flush start processing happening while
- * the chain function is also happening.
- */
- GMutex flush_lock;
-
- /* properties */
- gboolean emit_signals;
-};
-
-/* Must be called with PAD_LOCK held */
-static void
-gst_aggregator_pad_reset_unlocked (GstAggregatorPad * aggpad)
-{
- aggpad->priv->eos = FALSE;
- aggpad->priv->flow_return = GST_FLOW_OK;
- GST_OBJECT_LOCK (aggpad);
- gst_segment_init (&aggpad->segment, GST_FORMAT_UNDEFINED);
- gst_segment_init (&aggpad->priv->head_segment, GST_FORMAT_UNDEFINED);
- GST_OBJECT_UNLOCK (aggpad);
- aggpad->priv->head_position = GST_CLOCK_TIME_NONE;
- aggpad->priv->tail_position = GST_CLOCK_TIME_NONE;
- aggpad->priv->head_time = GST_CLOCK_TIME_NONE;
- aggpad->priv->tail_time = GST_CLOCK_TIME_NONE;
- aggpad->priv->time_level = 0;
- aggpad->priv->first_buffer = TRUE;
-}
-
-static gboolean
-gst_aggregator_pad_flush (GstAggregatorPad * aggpad, GstAggregator * agg)
-{
- GstAggregatorPadClass *klass = GST_AGGREGATOR_PAD_GET_CLASS (aggpad);
-
- PAD_LOCK (aggpad);
- gst_aggregator_pad_reset_unlocked (aggpad);
- PAD_UNLOCK (aggpad);
-
- if (klass->flush)
- return (klass->flush (aggpad, agg) == GST_FLOW_OK);
-
- return TRUE;
-}
-
-/**
- * gst_aggregator_peek_next_sample:
- *
- * Use this function to determine what input buffers will be aggregated
- * to produce the next output buffer. This should only be called from
- * a #GstAggregator::samples-selected handler, and can be used to precisely
- * control aggregating parameters for a given set of input samples.
- *
- * Returns: (nullable) (transfer full): The sample that is about to be aggregated. It may hold a #GstBuffer
- * or a #GstBufferList. The contents of its info structure is subclass-dependent,
- * and documented on a subclass basis. The buffers held by the sample are
- * not writable.
- * Since: 1.18
- */
-GstSample *
-gst_aggregator_peek_next_sample (GstAggregator * agg, GstAggregatorPad * aggpad)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (agg);
-
- if (klass->peek_next_sample)
- return (klass->peek_next_sample (agg, aggpad));
-
- return NULL;
-}
-
-/*************************************
- * GstAggregator implementation *
- *************************************/
-static GstElementClass *aggregator_parent_class = NULL;
-static gint aggregator_private_offset = 0;
-
-/* All members are protected by the object lock unless otherwise noted */
-
-struct _GstAggregatorPrivate
-{
- gint max_padserial;
-
- /* Our state is >= PAUSED */
- gboolean running; /* protected by src_lock */
-
- /* seqnum from last seek or common seqnum to flush start events received
- * on all pads, for flushing without a seek */
- guint32 next_seqnum;
- /* seqnum to apply to synthetic segment/eos events */
- guint32 seqnum;
- gboolean send_stream_start; /* protected by srcpad stream lock */
- gboolean send_segment;
- gboolean flushing;
- gboolean send_eos; /* protected by srcpad stream lock */
-
- GstCaps *srccaps; /* protected by the srcpad stream lock */
-
- GstTagList *tags;
- gboolean tags_changed;
-
- gboolean peer_latency_live; /* protected by src_lock */
- GstClockTime peer_latency_min; /* protected by src_lock */
- GstClockTime peer_latency_max; /* protected by src_lock */
- gboolean has_peer_latency; /* protected by src_lock */
-
- GstClockTime sub_latency_min; /* protected by src_lock */
- GstClockTime sub_latency_max; /* protected by src_lock */
-
- GstClockTime upstream_latency_min; /* protected by src_lock */
-
- /* aggregate */
- GstClockID aggregate_id; /* protected by src_lock */
- gboolean selected_samples_called_or_warned; /* protected by src_lock */
- GMutex src_lock;
- GCond src_cond;
-
- gboolean first_buffer; /* protected by object lock */
- GstAggregatorStartTimeSelection start_time_selection;
- GstClockTime start_time;
-
- /* protected by the object lock */
- GstQuery *allocation_query;
- GstAllocator *allocator;
- GstBufferPool *pool;
- GstAllocationParams allocation_params;
-
- /* properties */
- gint64 latency; /* protected by both src_lock and all pad locks */
- gboolean emit_signals;
-};
-
-/* Seek event forwarding helper */
-typedef struct
-{
- /* parameters */
- GstEvent *event;
- gboolean flush;
- gboolean only_to_active_pads;
-
- /* results */
- gboolean result;
- gboolean one_actually_seeked;
-} EventData;
-
-#define DEFAULT_LATENCY 0
-#define DEFAULT_MIN_UPSTREAM_LATENCY 0
-#define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO
-#define DEFAULT_START_TIME (-1)
-#define DEFAULT_EMIT_SIGNALS FALSE
-
-enum
-{
- PROP_0,
- PROP_LATENCY,
- PROP_MIN_UPSTREAM_LATENCY,
- PROP_START_TIME_SELECTION,
- PROP_START_TIME,
- PROP_EMIT_SIGNALS,
- PROP_LAST
-};
-
-enum
-{
- SIGNAL_SAMPLES_SELECTED,
- LAST_SIGNAL,
-};
-
-static guint gst_aggregator_signals[LAST_SIGNAL] = { 0 };
-
-static GstFlowReturn gst_aggregator_pad_chain_internal (GstAggregator * self,
- GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head);
-
-static gboolean
-gst_aggregator_pad_queue_is_empty (GstAggregatorPad * pad)
-{
- return (g_queue_peek_tail (&pad->priv->data) == NULL &&
- pad->priv->clipped_buffer == NULL);
-}
-
-/* Will return FALSE if there's no buffer available on every non-EOS pad, or
- * if at least one of the pads has an event or query at the top of its queue.
- *
- * Only returns TRUE if all non-EOS pads have a buffer available at the top of
- * their queue or a clipped buffer already.
- */
-static gboolean
-gst_aggregator_check_pads_ready (GstAggregator * self,
- gboolean * have_event_or_query_ret)
-{
- GstAggregatorPad *pad = NULL;
- GList *l, *sinkpads;
- gboolean have_buffer = TRUE;
- gboolean have_event_or_query = FALSE;
-
- GST_LOG_OBJECT (self, "checking pads");
-
- GST_OBJECT_LOCK (self);
-
- sinkpads = GST_ELEMENT_CAST (self)->sinkpads;
- if (sinkpads == NULL)
- goto no_sinkpads;
-
- for (l = sinkpads; l != NULL; l = l->next) {
- pad = l->data;
-
- PAD_LOCK (pad);
-
- /* If there's an event or query at the top of the queue and we don't yet
- * have taken the top buffer out and stored it as clip_buffer, remember
- * that and exit the loop. We first have to handle all events/queries
- * before we handle any buffers. */
- if (!pad->priv->clipped_buffer
- && (GST_IS_EVENT (g_queue_peek_tail (&pad->priv->data))
- || GST_IS_QUERY (g_queue_peek_tail (&pad->priv->data)))) {
- PAD_UNLOCK (pad);
- have_event_or_query = TRUE;
- break;
- }
-
- /* Otherwise check if we have a clipped buffer or a buffer at the top of
- * the queue, and if not then this pad is not ready unless it is also EOS */
- if (!pad->priv->clipped_buffer
- && !GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) {
- /* We must not have any buffers at all in this pad then as otherwise we
- * would've had an event/query at the top of the queue */
- g_assert (pad->priv->num_buffers == 0);
-
- /* Only consider this pad as worth waiting for if it's not already EOS.
- * There's no point in waiting for buffers on EOS pads */
- if (!pad->priv->eos)
- have_buffer = FALSE;
- } else if (self->priv->peer_latency_live) {
- /* In live mode, having a single pad with buffers is enough to
- * generate a start time from it. In non-live mode all pads need
- * to have a buffer
- */
- self->priv->first_buffer = FALSE;
- }
-
- PAD_UNLOCK (pad);
- }
-
- if (have_event_or_query)
- goto pad_not_ready_but_event_or_query;
-
- if (!have_buffer)
- goto pad_not_ready;
-
- if (have_buffer)
- self->priv->first_buffer = FALSE;
-
- GST_OBJECT_UNLOCK (self);
- GST_LOG_OBJECT (self, "pads are ready");
-
- if (have_event_or_query_ret)
- *have_event_or_query_ret = have_event_or_query;
-
- return TRUE;
-
-no_sinkpads:
- {
- GST_LOG_OBJECT (self, "pads not ready: no sink pads");
- GST_OBJECT_UNLOCK (self);
-
- if (have_event_or_query_ret)
- *have_event_or_query_ret = have_event_or_query;
-
- return FALSE;
- }
-pad_not_ready:
- {
- GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet");
- GST_OBJECT_UNLOCK (self);
-
- if (have_event_or_query_ret)
- *have_event_or_query_ret = have_event_or_query;
-
- return FALSE;
- }
-pad_not_ready_but_event_or_query:
- {
- GST_LOG_OBJECT (pad,
- "pad not ready to be aggregated yet, need to handle serialized event or query first");
- GST_OBJECT_UNLOCK (self);
-
- if (have_event_or_query_ret)
- *have_event_or_query_ret = have_event_or_query;
-
- return FALSE;
- }
-}
-
-static void
-gst_aggregator_reset_flow_values (GstAggregator * self)
-{
- GST_OBJECT_LOCK (self);
- self->priv->send_stream_start = TRUE;
- self->priv->send_segment = TRUE;
- gst_segment_init (&GST_AGGREGATOR_PAD (self->srcpad)->segment,
- GST_FORMAT_TIME);
- /* Initialize to -1 so we set it to the start position once the first buffer
- * is handled in gst_aggregator_pad_chain_internal() */
- GST_AGGREGATOR_PAD (self->srcpad)->segment.position = -1;
- self->priv->first_buffer = TRUE;
- GST_OBJECT_UNLOCK (self);
-}
-
-static inline void
-gst_aggregator_push_mandatory_events (GstAggregator * self)
-{
- GstAggregatorPrivate *priv = self->priv;
- GstEvent *segment = NULL;
- GstEvent *tags = NULL;
-
- if (self->priv->send_stream_start) {
- gchar s_id[32];
-
- GST_INFO_OBJECT (self, "pushing stream start");
- /* stream-start (FIXME: create id based on input ids) */
- g_snprintf (s_id, sizeof (s_id), "agg-%08x", g_random_int ());
- if (!gst_pad_push_event (GST_PAD (self->srcpad),
- gst_event_new_stream_start (s_id))) {
- GST_WARNING_OBJECT (self->srcpad, "Sending stream start event failed");
- }
- self->priv->send_stream_start = FALSE;
- }
-
- if (self->priv->srccaps) {
-
- GST_INFO_OBJECT (self, "pushing caps: %" GST_PTR_FORMAT,
- self->priv->srccaps);
- if (!gst_pad_push_event (GST_PAD (self->srcpad),
- gst_event_new_caps (self->priv->srccaps))) {
- GST_WARNING_OBJECT (self->srcpad, "Sending caps event failed");
- }
- gst_caps_unref (self->priv->srccaps);
- self->priv->srccaps = NULL;
- }
-
- GST_OBJECT_LOCK (self);
- if (self->priv->send_segment && !self->priv->flushing) {
- segment =
- gst_event_new_segment (&GST_AGGREGATOR_PAD (self->srcpad)->segment);
-
- if (!self->priv->seqnum)
- /* This code-path is in preparation to be able to run without a source
- * connected. Then we won't have a seq-num from a segment event. */
- self->priv->seqnum = gst_event_get_seqnum (segment);
- else
- gst_event_set_seqnum (segment, self->priv->seqnum);
- self->priv->send_segment = FALSE;
-
- GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segment);
- }
-
- if (priv->tags && priv->tags_changed && !self->priv->flushing) {
- tags = gst_event_new_tag (gst_tag_list_ref (priv->tags));
- priv->tags_changed = FALSE;
- }
- GST_OBJECT_UNLOCK (self);
-
- if (segment)
- gst_pad_push_event (self->srcpad, segment);
- if (tags)
- gst_pad_push_event (self->srcpad, tags);
-
-}
-
-/**
- * gst_aggregator_set_src_caps:
- * @self: The #GstAggregator
- * @caps: The #GstCaps to set on the src pad.
- *
- * Sets the caps to be used on the src pad.
- */
-void
-gst_aggregator_set_src_caps (GstAggregator * self, GstCaps * caps)
-{
- GST_PAD_STREAM_LOCK (self->srcpad);
- gst_caps_replace (&self->priv->srccaps, caps);
- gst_aggregator_push_mandatory_events (self);
- GST_PAD_STREAM_UNLOCK (self->srcpad);
-}
-
-static GstFlowReturn
-gst_aggregator_default_finish_buffer (GstAggregator * self, GstBuffer * buffer)
-{
- gst_aggregator_push_mandatory_events (self);
-
- GST_OBJECT_LOCK (self);
- if (!self->priv->flushing && gst_pad_is_active (self->srcpad)) {
- GST_TRACE_OBJECT (self, "pushing buffer %" GST_PTR_FORMAT, buffer);
- GST_OBJECT_UNLOCK (self);
- return gst_pad_push (self->srcpad, buffer);
- } else {
- GST_INFO_OBJECT (self, "Not pushing (active: %i, flushing: %i)",
- self->priv->flushing, gst_pad_is_active (self->srcpad));
- GST_OBJECT_UNLOCK (self);
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-}
-
-/**
- * gst_aggregator_finish_buffer:
- * @aggregator: The #GstAggregator
- * @buffer: (transfer full): the #GstBuffer to push.
- *
- * This method will push the provided output buffer downstream. If needed,
- * mandatory events such as stream-start, caps, and segment events will be
- * sent before pushing the buffer.
- */
-GstFlowReturn
-gst_aggregator_finish_buffer (GstAggregator * aggregator, GstBuffer * buffer)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (aggregator);
-
- g_assert (klass->finish_buffer != NULL);
-
- return klass->finish_buffer (aggregator, buffer);
-}
-
-static GstFlowReturn
-gst_aggregator_default_finish_buffer_list (GstAggregator * self,
- GstBufferList * bufferlist)
-{
- gst_aggregator_push_mandatory_events (self);
-
- GST_OBJECT_LOCK (self);
- if (!self->priv->flushing && gst_pad_is_active (self->srcpad)) {
- GST_TRACE_OBJECT (self, "pushing bufferlist%" GST_PTR_FORMAT, bufferlist);
- GST_OBJECT_UNLOCK (self);
- return gst_pad_push_list (self->srcpad, bufferlist);
- } else {
- GST_INFO_OBJECT (self, "Not pushing (active: %i, flushing: %i)",
- self->priv->flushing, gst_pad_is_active (self->srcpad));
- GST_OBJECT_UNLOCK (self);
- gst_buffer_list_unref (bufferlist);
- return GST_FLOW_OK;
- }
-}
-
-/**
- * gst_aggregator_finish_buffer_list:
- * @aggregator: The #GstAggregator
- * @bufferlist: (transfer full): the #GstBufferList to push.
- *
- * This method will push the provided output buffer list downstream. If needed,
- * mandatory events such as stream-start, caps, and segment events will be
- * sent before pushing the buffer.
- *
- * Since: 1.18
- */
-GstFlowReturn
-gst_aggregator_finish_buffer_list (GstAggregator * aggregator,
- GstBufferList * bufferlist)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (aggregator);
-
- g_assert (klass->finish_buffer_list != NULL);
-
- return klass->finish_buffer_list (aggregator, bufferlist);
-}
-
-static void
-gst_aggregator_push_eos (GstAggregator * self)
-{
- GstEvent *event;
- gst_aggregator_push_mandatory_events (self);
-
- event = gst_event_new_eos ();
-
- GST_OBJECT_LOCK (self);
- self->priv->send_eos = FALSE;
- gst_event_set_seqnum (event, self->priv->seqnum);
- GST_OBJECT_UNLOCK (self);
-
- gst_pad_push_event (self->srcpad, event);
-}
-
-static GstClockTime
-gst_aggregator_get_next_time (GstAggregator * self)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (klass->get_next_time)
- return klass->get_next_time (self);
-
- return GST_CLOCK_TIME_NONE;
-}
-
-static gboolean
-gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
-{
- GstClockTime latency;
- GstClockTime start;
- gboolean res;
- gboolean have_event_or_query = FALSE;
-
- *timeout = FALSE;
-
- SRC_LOCK (self);
-
- latency = gst_aggregator_get_latency_unlocked (self);
-
- if (gst_aggregator_check_pads_ready (self, &have_event_or_query)) {
- GST_DEBUG_OBJECT (self, "all pads have data");
- SRC_UNLOCK (self);
-
- return TRUE;
- }
-
- /* If we have an event or query, immediately return FALSE instead of waiting
- * and handle it immediately */
- if (have_event_or_query) {
- GST_DEBUG_OBJECT (self, "Have serialized event or query to handle first");
- SRC_UNLOCK (self);
- return FALSE;
- }
-
- /* Before waiting, check if we're actually still running */
- if (!self->priv->running || !self->priv->send_eos) {
- SRC_UNLOCK (self);
-
- return FALSE;
- }
-
- start = gst_aggregator_get_next_time (self);
-
- /* If we're not live, or if we use the running time
- * of the first buffer as start time, we wait until
- * all pads have buffers.
- * Otherwise (i.e. if we are live!), we wait on the clock
- * and if a pad does not have a buffer in time we ignore
- * that pad.
- */
- GST_OBJECT_LOCK (self);
- if (!GST_CLOCK_TIME_IS_VALID (latency) ||
- !GST_IS_CLOCK (GST_ELEMENT_CLOCK (self)) ||
- !GST_CLOCK_TIME_IS_VALID (start) ||
- (self->priv->first_buffer
- && self->priv->start_time_selection ==
- GST_AGGREGATOR_START_TIME_SELECTION_FIRST)) {
- /* We wake up here when something happened, and below
- * then check if we're ready now. If we return FALSE,
- * we will be directly called again.
- */
- GST_OBJECT_UNLOCK (self);
- SRC_WAIT (self);
- } else {
- GstClockTime base_time, time;
- GstClock *clock;
- GstClockReturn status;
- GstClockTimeDiff jitter;
-
- GST_DEBUG_OBJECT (self, "got subclass start time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start));
-
- base_time = GST_ELEMENT_CAST (self)->base_time;
- clock = gst_object_ref (GST_ELEMENT_CLOCK (self));
- GST_OBJECT_UNLOCK (self);
-
- time = base_time + start;
- time += latency;
-
- GST_DEBUG_OBJECT (self, "possibly waiting for clock to reach %"
- GST_TIME_FORMAT " (base %" GST_TIME_FORMAT " start %" GST_TIME_FORMAT
- " latency %" GST_TIME_FORMAT " current %" GST_TIME_FORMAT ")",
- GST_TIME_ARGS (time),
- GST_TIME_ARGS (base_time),
- GST_TIME_ARGS (start), GST_TIME_ARGS (latency),
- GST_TIME_ARGS (gst_clock_get_time (clock)));
-
- self->priv->aggregate_id = gst_clock_new_single_shot_id (clock, time);
- gst_object_unref (clock);
- SRC_UNLOCK (self);
-
- jitter = 0;
- status = gst_clock_id_wait (self->priv->aggregate_id, &jitter);
-
- SRC_LOCK (self);
- if (self->priv->aggregate_id) {
- gst_clock_id_unref (self->priv->aggregate_id);
- self->priv->aggregate_id = NULL;
- }
-
- GST_DEBUG_OBJECT (self,
- "clock returned %d (jitter: %" GST_STIME_FORMAT ")",
- status, GST_STIME_ARGS (jitter));
-
- /* we timed out */
- if (status == GST_CLOCK_OK || status == GST_CLOCK_EARLY) {
- SRC_UNLOCK (self);
- *timeout = TRUE;
- return TRUE;
- }
- }
-
- res = gst_aggregator_check_pads_ready (self, NULL);
- SRC_UNLOCK (self);
-
- return res;
-}
-
-typedef struct
-{
- gboolean processed_event;
- GstFlowReturn flow_ret;
-} DoHandleEventsAndQueriesData;
-
-static gboolean
-gst_aggregator_do_events_and_queries (GstElement * self, GstPad * epad,
- gpointer user_data)
-{
- GstAggregatorPad *pad = GST_AGGREGATOR_PAD_CAST (epad);
- GstAggregator *aggregator = GST_AGGREGATOR_CAST (self);
- GstEvent *event = NULL;
- GstQuery *query = NULL;
- GstAggregatorClass *klass = NULL;
- DoHandleEventsAndQueriesData *data = user_data;
-
- do {
- event = NULL;
- query = NULL;
-
- PAD_LOCK (pad);
- if (pad->priv->clipped_buffer == NULL &&
- !GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) {
- if (GST_IS_EVENT (g_queue_peek_tail (&pad->priv->data)))
- event = gst_event_ref (g_queue_peek_tail (&pad->priv->data));
- if (GST_IS_QUERY (g_queue_peek_tail (&pad->priv->data)))
- query = g_queue_peek_tail (&pad->priv->data);
- }
- PAD_UNLOCK (pad);
- if (event || query) {
- gboolean ret;
-
- data->processed_event = TRUE;
- if (klass == NULL)
- klass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (event) {
- GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, event);
- gst_event_ref (event);
- ret = klass->sink_event (aggregator, pad, event);
-
- PAD_LOCK (pad);
- if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
- pad->priv->negotiated = ret;
- }
- if (g_queue_peek_tail (&pad->priv->data) == event)
- gst_event_unref (g_queue_pop_tail (&pad->priv->data));
- gst_event_unref (event);
- } else if (query) {
- GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, query);
- ret = klass->sink_query (aggregator, pad, query);
-
- PAD_LOCK (pad);
- if (g_queue_peek_tail (&pad->priv->data) == query) {
- GstStructure *s;
-
- s = gst_query_writable_structure (query);
- gst_structure_set (s, "gst-aggregator-retval", G_TYPE_BOOLEAN, ret,
- NULL);
- g_queue_pop_tail (&pad->priv->data);
- }
- }
-
- PAD_BROADCAST_EVENT (pad);
- PAD_UNLOCK (pad);
- }
- } while (event || query);
-
- return TRUE;
-}
-
-static gboolean
-gst_aggregator_pad_skip_buffers (GstElement * self, GstPad * epad,
- gpointer user_data)
-{
- GList *item;
- GstAggregatorPad *aggpad = (GstAggregatorPad *) epad;
- GstAggregator *agg = (GstAggregator *) self;
- GstAggregatorPadClass *klass = GST_AGGREGATOR_PAD_GET_CLASS (aggpad);
-
- if (!klass->skip_buffer)
- return FALSE;
-
- PAD_LOCK (aggpad);
-
- item = g_queue_peek_tail_link (&aggpad->priv->data);
- while (item) {
- GList *prev = item->prev;
-
- if (GST_IS_BUFFER (item->data)
- && klass->skip_buffer (aggpad, agg, item->data)) {
- GST_LOG_OBJECT (aggpad, "Skipping %" GST_PTR_FORMAT, item->data);
- gst_aggregator_pad_buffer_consumed (aggpad, GST_BUFFER (item->data),
- TRUE);
- gst_buffer_unref (item->data);
- g_queue_delete_link (&aggpad->priv->data, item);
- } else {
- break;
- }
-
- item = prev;
- }
-
- PAD_UNLOCK (aggpad);
-
- return TRUE;
-}
-
-static gboolean
-gst_aggregator_pad_reset_peeked_buffer (GstElement * self, GstPad * epad,
- gpointer user_data)
-{
- GstAggregatorPad *aggpad = (GstAggregatorPad *) epad;
-
- PAD_LOCK (aggpad);
-
- gst_buffer_replace (&aggpad->priv->peeked_buffer, NULL);
-
- PAD_UNLOCK (aggpad);
-
- return TRUE;
-}
-
-
-static void
-gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad,
- GstFlowReturn flow_return, gboolean full)
-{
- GList *item;
-
- PAD_LOCK (aggpad);
- if (flow_return == GST_FLOW_NOT_LINKED)
- aggpad->priv->flow_return = MIN (flow_return, aggpad->priv->flow_return);
- else
- aggpad->priv->flow_return = flow_return;
-
- item = g_queue_peek_head_link (&aggpad->priv->data);
- while (item) {
- GList *next = item->next;
-
- /* In partial flush, we do like the pad, we get rid of non-sticky events
- * and EOS/SEGMENT.
- */
- if (full || GST_IS_BUFFER (item->data) ||
- GST_EVENT_TYPE (item->data) == GST_EVENT_EOS ||
- GST_EVENT_TYPE (item->data) == GST_EVENT_SEGMENT ||
- !GST_EVENT_IS_STICKY (item->data)) {
- if (!GST_IS_QUERY (item->data))
- gst_mini_object_unref (item->data);
- g_queue_delete_link (&aggpad->priv->data, item);
- }
- item = next;
- }
- aggpad->priv->num_buffers = 0;
- gst_buffer_replace (&aggpad->priv->clipped_buffer, NULL);
-
- PAD_BROADCAST_EVENT (aggpad);
- PAD_UNLOCK (aggpad);
-}
-
-static GstFlowReturn
-gst_aggregator_default_update_src_caps (GstAggregator * agg, GstCaps * caps,
- GstCaps ** ret)
-{
- *ret = gst_caps_ref (caps);
-
- return GST_FLOW_OK;
-}
-
-static GstCaps *
-gst_aggregator_default_fixate_src_caps (GstAggregator * agg, GstCaps * caps)
-{
- caps = gst_caps_fixate (caps);
-
- return caps;
-}
-
-static gboolean
-gst_aggregator_default_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
-{
- return TRUE;
-}
-
-
-/* takes ownership of the pool, allocator and query */
-static gboolean
-gst_aggregator_set_allocation (GstAggregator * self,
- GstBufferPool * pool, GstAllocator * allocator,
- const GstAllocationParams * params, GstQuery * query)
-{
- GstAllocator *oldalloc;
- GstBufferPool *oldpool;
- GstQuery *oldquery;
-
- GST_DEBUG ("storing allocation query");
-
- GST_OBJECT_LOCK (self);
- oldpool = self->priv->pool;
- self->priv->pool = pool;
-
- oldalloc = self->priv->allocator;
- self->priv->allocator = allocator;
-
- oldquery = self->priv->allocation_query;
- self->priv->allocation_query = query;
-
- if (params)
- self->priv->allocation_params = *params;
- else
- gst_allocation_params_init (&self->priv->allocation_params);
- GST_OBJECT_UNLOCK (self);
-
- if (oldpool) {
- GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool);
- gst_buffer_pool_set_active (oldpool, FALSE);
- gst_object_unref (oldpool);
- }
- if (oldalloc) {
- gst_object_unref (oldalloc);
- }
- if (oldquery) {
- gst_query_unref (oldquery);
- }
- return TRUE;
-}
-
-
-static gboolean
-gst_aggregator_decide_allocation (GstAggregator * self, GstQuery * query)
-{
- GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (aggclass->decide_allocation)
- if (!aggclass->decide_allocation (self, query))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-gst_aggregator_do_allocation (GstAggregator * self, GstCaps * caps)
-{
- GstQuery *query;
- gboolean result = TRUE;
- GstBufferPool *pool = NULL;
- GstAllocator *allocator;
- GstAllocationParams params;
-
- /* find a pool for the negotiated caps now */
- GST_DEBUG_OBJECT (self, "doing allocation query");
- query = gst_query_new_allocation (caps, TRUE);
- if (!gst_pad_peer_query (self->srcpad, query)) {
- /* not a problem, just debug a little */
- GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed");
- }
-
- GST_DEBUG_OBJECT (self, "calling decide_allocation");
- result = gst_aggregator_decide_allocation (self, query);
-
- GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
- query);
-
- if (!result)
- goto no_decide_allocation;
-
- /* we got configuration from our peer or the decide_allocation method,
- * parse them */
- if (gst_query_get_n_allocation_params (query) > 0) {
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0)
- gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
-
- /* now store */
- result =
- gst_aggregator_set_allocation (self, pool, allocator, &params, query);
-
- return result;
-
- /* Errors */
-no_decide_allocation:
- {
- GST_WARNING_OBJECT (self, "Failed to decide allocation");
- gst_query_unref (query);
-
- return result;
- }
-
-}
-
-static gboolean
-gst_aggregator_default_negotiate (GstAggregator * self)
-{
- GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self);
- GstCaps *downstream_caps, *template_caps, *caps = NULL;
- GstFlowReturn ret = GST_FLOW_OK;
-
- template_caps = gst_pad_get_pad_template_caps (self->srcpad);
- downstream_caps = gst_pad_peer_query_caps (self->srcpad, template_caps);
-
- if (gst_caps_is_empty (downstream_caps)) {
- GST_INFO_OBJECT (self, "Downstream caps (%"
- GST_PTR_FORMAT ") not compatible with pad template caps (%"
- GST_PTR_FORMAT ")", downstream_caps, template_caps);
- ret = GST_FLOW_NOT_NEGOTIATED;
- goto done;
- }
-
- g_assert (agg_klass->update_src_caps);
- GST_DEBUG_OBJECT (self, "updating caps from %" GST_PTR_FORMAT,
- downstream_caps);
- ret = agg_klass->update_src_caps (self, downstream_caps, &caps);
- if (ret < GST_FLOW_OK) {
- GST_WARNING_OBJECT (self, "Subclass failed to update provided caps");
- goto done;
- } else if (ret == GST_AGGREGATOR_FLOW_NEED_DATA) {
- GST_DEBUG_OBJECT (self, "Subclass needs more data to decide on caps");
- goto done;
- }
- if ((caps == NULL || gst_caps_is_empty (caps)) && ret >= GST_FLOW_OK) {
- ret = GST_FLOW_NOT_NEGOTIATED;
- goto done;
- }
- GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps);
-
-#ifdef GST_ENABLE_EXTRA_CHECKS
- if (!gst_caps_is_subset (caps, template_caps)) {
- GstCaps *intersection;
-
- GST_ERROR_OBJECT (self,
- "update_src_caps returned caps %" GST_PTR_FORMAT
- " which are not a real subset of the template caps %"
- GST_PTR_FORMAT, caps, template_caps);
- g_warning ("%s: update_src_caps returned caps which are not a real "
- "subset of the filter caps", GST_ELEMENT_NAME (self));
-
- intersection =
- gst_caps_intersect_full (template_caps, caps, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (caps);
- caps = intersection;
- }
-#endif
-
- if (gst_caps_is_any (caps)) {
- goto done;
- }
-
- if (!gst_caps_is_fixed (caps)) {
- g_assert (agg_klass->fixate_src_caps);
-
- GST_DEBUG_OBJECT (self, "fixate caps from %" GST_PTR_FORMAT, caps);
- if (!(caps = agg_klass->fixate_src_caps (self, caps))) {
- GST_WARNING_OBJECT (self, "Subclass failed to fixate provided caps");
- ret = GST_FLOW_NOT_NEGOTIATED;
- goto done;
- }
- GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps);
- }
-
- if (agg_klass->negotiated_src_caps) {
- if (!agg_klass->negotiated_src_caps (self, caps)) {
- GST_WARNING_OBJECT (self, "Subclass failed to accept negotiated caps");
- ret = GST_FLOW_NOT_NEGOTIATED;
- goto done;
- }
- }
-
- gst_aggregator_set_src_caps (self, caps);
-
- if (!gst_aggregator_do_allocation (self, caps)) {
- GST_WARNING_OBJECT (self, "Allocation negotiation failed");
- ret = GST_FLOW_NOT_NEGOTIATED;
- }
-
-done:
- gst_caps_unref (downstream_caps);
- gst_caps_unref (template_caps);
-
- if (caps)
- gst_caps_unref (caps);
-
- return ret >= GST_FLOW_OK || ret == GST_AGGREGATOR_FLOW_NEED_DATA;
-}
-
-/* WITH SRC_LOCK held */
-static gboolean
-gst_aggregator_negotiate_unlocked (GstAggregator * self)
-{
- GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (agg_klass->negotiate)
- return agg_klass->negotiate (self);
-
- return TRUE;
-}
-
-/**
- * gst_aggregator_negotiate:
- * @self: a #GstAggregator
- *
- * Negotiates src pad caps with downstream elements.
- * Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
- * if #GstAggregatorClass::negotiate fails.
- *
- * Returns: %TRUE if the negotiation succeeded, else %FALSE.
- *
- * Since: 1.18
- */
-gboolean
-gst_aggregator_negotiate (GstAggregator * self)
-{
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_AGGREGATOR (self), FALSE);
-
- GST_PAD_STREAM_LOCK (GST_AGGREGATOR_SRC_PAD (self));
- gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
- ret = gst_aggregator_negotiate_unlocked (self);
- if (!ret)
- gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
- GST_PAD_STREAM_UNLOCK (GST_AGGREGATOR_SRC_PAD (self));
-
- return ret;
-}
-
-static void
-gst_aggregator_aggregate_func (GstAggregator * self)
-{
- GstAggregatorPrivate *priv = self->priv;
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
- gboolean timeout = FALSE;
-
- if (self->priv->running == FALSE) {
- GST_DEBUG_OBJECT (self, "Not running anymore");
- return;
- }
-
- GST_LOG_OBJECT (self, "Checking aggregate");
- while (priv->send_eos && priv->running) {
- GstFlowReturn flow_return = GST_FLOW_OK;
- DoHandleEventsAndQueriesData events_query_data = { FALSE, GST_FLOW_OK };
-
- gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
- gst_aggregator_do_events_and_queries, &events_query_data);
-
- if ((flow_return = events_query_data.flow_ret) != GST_FLOW_OK)
- goto handle_error;
-
- if (self->priv->peer_latency_live)
- gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
- gst_aggregator_pad_skip_buffers, NULL);
-
- /* Ensure we have buffers ready (either in clipped_buffer or at the head of
- * the queue */
- if (!gst_aggregator_wait_and_check (self, &timeout)) {
- gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
- gst_aggregator_pad_reset_peeked_buffer, NULL);
- continue;
- }
-
- if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self))) {
- if (!gst_aggregator_negotiate_unlocked (self)) {
- gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
- if (GST_PAD_IS_FLUSHING (GST_AGGREGATOR_SRC_PAD (self))) {
- flow_return = GST_FLOW_FLUSHING;
- } else {
- flow_return = GST_FLOW_NOT_NEGOTIATED;
- }
- }
- }
-
- if (timeout || flow_return >= GST_FLOW_OK) {
- GST_TRACE_OBJECT (self, "Actually aggregating!");
- flow_return = klass->aggregate (self, timeout);
- }
-
- gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
- gst_aggregator_pad_reset_peeked_buffer, NULL);
-
- if (!priv->selected_samples_called_or_warned) {
- GST_FIXME_OBJECT (self,
- "Subclass should call gst_aggregator_selected_samples() from its "
- "aggregate implementation.");
- priv->selected_samples_called_or_warned = TRUE;
- }
-
- if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA)
- continue;
-
- GST_OBJECT_LOCK (self);
- if (flow_return == GST_FLOW_FLUSHING && priv->flushing) {
- /* We don't want to set the pads to flushing, but we want to
- * stop the thread, so just break here */
- GST_OBJECT_UNLOCK (self);
- break;
- }
- GST_OBJECT_UNLOCK (self);
-
- if (flow_return == GST_FLOW_EOS || flow_return == GST_FLOW_ERROR) {
- gst_aggregator_push_eos (self);
- }
-
- handle_error:
- GST_LOG_OBJECT (self, "flow return is %s", gst_flow_get_name (flow_return));
-
- if (flow_return != GST_FLOW_OK) {
- GList *item;
-
- GST_OBJECT_LOCK (self);
- for (item = GST_ELEMENT (self)->sinkpads; item; item = item->next) {
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data);
-
- gst_aggregator_pad_set_flushing (aggpad, flow_return, TRUE);
- }
- GST_OBJECT_UNLOCK (self);
- break;
- }
- }
-
- /* Pause the task here, the only ways to get here are:
- * 1) We're stopping, in which case the task is stopped anyway
- * 2) We got a flow error above, in which case it might take
- * some time to forward the flow return upstream and we
- * would otherwise call the task function over and over
- * again without doing anything
- */
- gst_pad_pause_task (self->srcpad);
-}
-
-static gboolean
-gst_aggregator_start (GstAggregator * self)
-{
- GstAggregatorClass *klass;
- gboolean result;
-
- self->priv->send_stream_start = TRUE;
- self->priv->send_segment = TRUE;
- self->priv->send_eos = TRUE;
- self->priv->srccaps = NULL;
-
- self->priv->has_peer_latency = FALSE;
- self->priv->peer_latency_live = FALSE;
- self->priv->peer_latency_min = self->priv->peer_latency_max = 0;
-
- gst_aggregator_set_allocation (self, NULL, NULL, NULL, NULL);
-
- klass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (klass->start)
- result = klass->start (self);
- else
- result = TRUE;
-
- return result;
-}
-
-static gboolean
-gst_aggregator_stop_srcpad_task (GstAggregator * self, GstEvent * flush_start)
-{
- gboolean res = TRUE;
-
- GST_INFO_OBJECT (self, "%s srcpad task",
- flush_start ? "Pausing" : "Stopping");
-
- SRC_LOCK (self);
- self->priv->running = FALSE;
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
-
- if (flush_start) {
- res = gst_pad_push_event (self->srcpad, flush_start);
- }
-
- gst_pad_stop_task (self->srcpad);
-
- return res;
-}
-
-static void
-gst_aggregator_start_srcpad_task (GstAggregator * self)
-{
- GST_INFO_OBJECT (self, "Starting srcpad task");
-
- self->priv->running = TRUE;
- gst_pad_start_task (GST_PAD (self->srcpad),
- (GstTaskFunction) gst_aggregator_aggregate_func, self, NULL);
-}
-
-static GstFlowReturn
-gst_aggregator_flush (GstAggregator * self)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstAggregatorPrivate *priv = self->priv;
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
-
- GST_DEBUG_OBJECT (self, "Flushing everything");
- GST_OBJECT_LOCK (self);
- priv->send_segment = TRUE;
- priv->flushing = FALSE;
- priv->tags_changed = FALSE;
- GST_OBJECT_UNLOCK (self);
- if (klass->flush)
- ret = klass->flush (self);
-
- return ret;
-}
-
-
-/* Called with GstAggregator's object lock held */
-
-static gboolean
-gst_aggregator_all_flush_stop_received (GstAggregator * self, guint32 seqnum)
-{
- GList *tmp;
- GstAggregatorPad *tmppad;
-
- for (tmp = GST_ELEMENT (self)->sinkpads; tmp; tmp = tmp->next) {
- tmppad = (GstAggregatorPad *) tmp->data;
-
- if (tmppad->priv->last_flush_stop_seqnum != seqnum)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Called with GstAggregator's object lock held */
-
-static gboolean
-gst_aggregator_all_flush_start_received (GstAggregator * self, guint32 seqnum)
-{
- GList *tmp;
- GstAggregatorPad *tmppad;
-
- for (tmp = GST_ELEMENT (self)->sinkpads; tmp; tmp = tmp->next) {
- tmppad = (GstAggregatorPad *) tmp->data;
-
- if (tmppad->priv->last_flush_start_seqnum != seqnum) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static void
-gst_aggregator_flush_start (GstAggregator * self, GstAggregatorPad * aggpad,
- GstEvent * event)
-{
- GstAggregatorPrivate *priv = self->priv;
- GstAggregatorPadPrivate *padpriv = aggpad->priv;
- guint32 seqnum = gst_event_get_seqnum (event);
-
- gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, FALSE);
-
- PAD_FLUSH_LOCK (aggpad);
- PAD_LOCK (aggpad);
- padpriv->last_flush_start_seqnum = seqnum;
- PAD_UNLOCK (aggpad);
-
- GST_OBJECT_LOCK (self);
-
- if (!priv->flushing && gst_aggregator_all_flush_start_received (self, seqnum)) {
- /* Make sure we don't forward more than one FLUSH_START */
- priv->flushing = TRUE;
- priv->next_seqnum = seqnum;
- GST_OBJECT_UNLOCK (self);
-
- GST_INFO_OBJECT (self, "Flushing, pausing srcpad task");
- gst_aggregator_stop_srcpad_task (self, event);
-
- event = NULL;
- } else {
- gst_event_unref (event);
- GST_OBJECT_UNLOCK (self);
- }
-
- PAD_FLUSH_UNLOCK (aggpad);
-}
-
-/* Must be called with the the PAD_LOCK held */
-static void
-update_time_level (GstAggregatorPad * aggpad, gboolean head)
-{
- GstAggregatorPadPrivate *priv = aggpad->priv;
-
- if (head) {
- if (GST_CLOCK_TIME_IS_VALID (priv->head_position) &&
- priv->head_segment.format == GST_FORMAT_TIME)
- priv->head_time = gst_segment_to_running_time (&priv->head_segment,
- GST_FORMAT_TIME, priv->head_position);
- else
- priv->head_time = GST_CLOCK_TIME_NONE;
-
- if (!GST_CLOCK_TIME_IS_VALID (priv->tail_time))
- priv->tail_time = priv->head_time;
- } else {
- if (GST_CLOCK_TIME_IS_VALID (priv->tail_position) &&
- aggpad->segment.format == GST_FORMAT_TIME)
- priv->tail_time = gst_segment_to_running_time (&aggpad->segment,
- GST_FORMAT_TIME, priv->tail_position);
- else
- priv->tail_time = priv->head_time;
- }
-
- if (priv->head_time == GST_CLOCK_TIME_NONE ||
- priv->tail_time == GST_CLOCK_TIME_NONE) {
- priv->time_level = 0;
- return;
- }
-
- if (priv->tail_time > priv->head_time)
- priv->time_level = 0;
- else
- priv->time_level = priv->head_time - priv->tail_time;
-}
-
-
-/* GstAggregator vmethods default implementations */
-static gboolean
-gst_aggregator_default_sink_event (GstAggregator * self,
- GstAggregatorPad * aggpad, GstEvent * event)
-{
- gboolean res = TRUE;
- GstPad *pad = GST_PAD (aggpad);
- GstAggregatorPrivate *priv = self->priv;
-
- GST_DEBUG_OBJECT (aggpad, "Got event: %" GST_PTR_FORMAT, event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- {
- gst_aggregator_flush_start (self, aggpad, event);
- /* We forward only in one case: right after flushing */
- event = NULL;
- goto eat;
- }
- case GST_EVENT_FLUSH_STOP:
- {
- guint32 seqnum = gst_event_get_seqnum (event);
-
- PAD_FLUSH_LOCK (aggpad);
- PAD_LOCK (aggpad);
- aggpad->priv->last_flush_stop_seqnum = seqnum;
- PAD_UNLOCK (aggpad);
-
- gst_aggregator_pad_flush (aggpad, self);
-
- GST_OBJECT_LOCK (self);
- if (priv->flushing
- && gst_aggregator_all_flush_stop_received (self, seqnum)) {
- GST_OBJECT_UNLOCK (self);
- /* That means we received FLUSH_STOP/FLUSH_STOP on
- * all sinkpads -- Seeking is Done... sending FLUSH_STOP */
- gst_aggregator_flush (self);
- gst_pad_push_event (self->srcpad, event);
- event = NULL;
- SRC_LOCK (self);
- priv->send_eos = TRUE;
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
-
- GST_INFO_OBJECT (self, "Flush stopped");
-
- gst_aggregator_start_srcpad_task (self);
- } else {
- GST_OBJECT_UNLOCK (self);
- }
-
- PAD_FLUSH_UNLOCK (aggpad);
-
- /* We never forward the event */
- goto eat;
- }
- case GST_EVENT_EOS:
- {
- SRC_LOCK (self);
- PAD_LOCK (aggpad);
- g_assert (aggpad->priv->num_buffers == 0);
- aggpad->priv->eos = TRUE;
- PAD_UNLOCK (aggpad);
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
- goto eat;
- }
- case GST_EVENT_SEGMENT:
- {
- PAD_LOCK (aggpad);
- GST_OBJECT_LOCK (aggpad);
- gst_event_copy_segment (event, &aggpad->segment);
- /* We've got a new segment, tail_position is now meaningless
- * and may interfere with the time_level calculation
- */
- aggpad->priv->tail_position = GST_CLOCK_TIME_NONE;
- update_time_level (aggpad, FALSE);
- GST_OBJECT_UNLOCK (aggpad);
- PAD_UNLOCK (aggpad);
-
- GST_OBJECT_LOCK (self);
- self->priv->seqnum = gst_event_get_seqnum (event);
- GST_OBJECT_UNLOCK (self);
- goto eat;
- }
- case GST_EVENT_STREAM_START:
- {
- goto eat;
- }
- case GST_EVENT_GAP:
- {
- GstClockTime pts, endpts;
- GstClockTime duration;
- GstBuffer *gapbuf;
-
- gst_event_parse_gap (event, &pts, &duration);
-
- if (GST_CLOCK_TIME_IS_VALID (duration))
- endpts = pts + duration;
- else
- endpts = GST_CLOCK_TIME_NONE;
-
- GST_OBJECT_LOCK (aggpad);
- res = gst_segment_clip (&aggpad->segment, GST_FORMAT_TIME, pts, endpts,
- &pts, &endpts);
- GST_OBJECT_UNLOCK (aggpad);
-
- if (!res) {
- GST_WARNING_OBJECT (self, "GAP event outside segment, dropping");
- goto eat;
- }
-
- if (GST_CLOCK_TIME_IS_VALID (endpts) && GST_CLOCK_TIME_IS_VALID (pts))
- duration = endpts - pts;
- else
- duration = GST_CLOCK_TIME_NONE;
-
- gapbuf = gst_buffer_new ();
- GST_BUFFER_PTS (gapbuf) = pts;
- GST_BUFFER_DURATION (gapbuf) = duration;
- GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_GAP);
- GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_DROPPABLE);
-
- /* Remove GAP event so we can replace it with the buffer */
- PAD_LOCK (aggpad);
- if (g_queue_peek_tail (&aggpad->priv->data) == event)
- gst_event_unref (g_queue_pop_tail (&aggpad->priv->data));
- PAD_UNLOCK (aggpad);
-
- if (gst_aggregator_pad_chain_internal (self, aggpad, gapbuf, FALSE) !=
- GST_FLOW_OK) {
- GST_WARNING_OBJECT (self, "Failed to chain gap buffer");
- res = FALSE;
- }
-
- goto eat;
- }
- case GST_EVENT_TAG:
- goto eat;
- default:
- {
- break;
- }
- }
-
- GST_DEBUG_OBJECT (pad, "Forwarding event: %" GST_PTR_FORMAT, event);
- return gst_pad_event_default (pad, GST_OBJECT (self), event);
-
-eat:
- GST_DEBUG_OBJECT (pad, "Eating event: %" GST_PTR_FORMAT, event);
- if (event)
- gst_event_unref (event);
-
- return res;
-}
-
-/* Queue serialized events and let the others go through directly.
- * The queued events with be handled from the src-pad task in
- * gst_aggregator_do_events_and_queries().
- */
-static GstFlowReturn
-gst_aggregator_default_sink_event_pre_queue (GstAggregator * self,
- GstAggregatorPad * aggpad, GstEvent * event)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- if (GST_EVENT_IS_SERIALIZED (event)
- && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
- SRC_LOCK (self);
- PAD_LOCK (aggpad);
-
- if (aggpad->priv->flow_return != GST_FLOW_OK)
- goto flushing;
-
- if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
- GST_OBJECT_LOCK (aggpad);
- gst_event_copy_segment (event, &aggpad->priv->head_segment);
- aggpad->priv->head_position = aggpad->priv->head_segment.position;
- update_time_level (aggpad, TRUE);
- GST_OBJECT_UNLOCK (aggpad);
- }
-
- GST_DEBUG_OBJECT (aggpad, "Store event in queue: %" GST_PTR_FORMAT, event);
- g_queue_push_head (&aggpad->priv->data, event);
- SRC_BROADCAST (self);
- PAD_UNLOCK (aggpad);
- SRC_UNLOCK (self);
- } else {
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
-
- if (!klass->sink_event (self, aggpad, event)) {
- /* Copied from GstPad to convert boolean to a GstFlowReturn in
- * the event handling func */
- ret = GST_FLOW_ERROR;
- }
- }
-
- return ret;
-
-flushing:
- GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping event",
- gst_flow_get_name (aggpad->priv->flow_return));
- PAD_UNLOCK (aggpad);
- SRC_UNLOCK (self);
- if (GST_EVENT_IS_STICKY (event))
- gst_pad_store_sticky_event (GST_PAD (aggpad), event);
- gst_event_unref (event);
-
- return aggpad->priv->flow_return;
-}
-
-static gboolean
-gst_aggregator_stop_pad (GstElement * self, GstPad * epad, gpointer user_data)
-{
- GstAggregatorPad *pad = GST_AGGREGATOR_PAD_CAST (epad);
- GstAggregator *agg = GST_AGGREGATOR_CAST (self);
-
- gst_aggregator_pad_flush (pad, agg);
-
- PAD_LOCK (pad);
- pad->priv->flow_return = GST_FLOW_FLUSHING;
- pad->priv->negotiated = FALSE;
- PAD_BROADCAST_EVENT (pad);
- PAD_UNLOCK (pad);
-
- return TRUE;
-}
-
-static gboolean
-gst_aggregator_stop (GstAggregator * agg)
-{
- GstAggregatorClass *klass;
- gboolean result;
-
- gst_aggregator_reset_flow_values (agg);
-
- /* Application needs to make sure no pads are added while it shuts us down */
- gst_element_foreach_sink_pad (GST_ELEMENT_CAST (agg),
- gst_aggregator_stop_pad, NULL);
-
- klass = GST_AGGREGATOR_GET_CLASS (agg);
-
- if (klass->stop)
- result = klass->stop (agg);
- else
- result = TRUE;
-
- agg->priv->has_peer_latency = FALSE;
- agg->priv->peer_latency_live = FALSE;
- agg->priv->peer_latency_min = agg->priv->peer_latency_max = 0;
-
- if (agg->priv->tags)
- gst_tag_list_unref (agg->priv->tags);
- agg->priv->tags = NULL;
-
- gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL);
-
- if (agg->priv->running) {
- /* As sinkpads get deactivated after the src pad, we
- * may have restarted the source pad task after receiving
- * flush events on one of our sinkpads. Stop our src pad
- * task again if that is the case */
- gst_aggregator_stop_srcpad_task (agg, NULL);
- }
-
- return result;
-}
-
-/* GstElement vmethods implementations */
-static GstStateChangeReturn
-gst_aggregator_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- GstAggregator *self = GST_AGGREGATOR (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- if (!gst_aggregator_start (self))
- goto error_start;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- /* Wake up any waiting as now we have a clock and can do
- * proper waiting on the clock if necessary */
- SRC_LOCK (self);
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
- break;
- default:
- break;
- }
-
- if ((ret =
- GST_ELEMENT_CLASS (aggregator_parent_class)->change_state (element,
- transition)) == GST_STATE_CHANGE_FAILURE)
- goto failure;
-
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- if (!gst_aggregator_stop (self)) {
- /* What to do in this case? Error out? */
- GST_ERROR_OBJECT (self, "Subclass failed to stop.");
- }
- break;
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- /* Wake up any waiting as now clock might be gone and we might
- * need to wait on the condition variable again */
- SRC_LOCK (self);
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
- break;
- default:
- break;
- }
-
- return ret;
-
-/* ERRORS */
-failure:
- {
- GST_ERROR_OBJECT (element, "parent failed state change");
- return ret;
- }
-error_start:
- {
- GST_ERROR_OBJECT (element, "Subclass failed to start");
- return GST_STATE_CHANGE_FAILURE;
- }
-}
-
-static void
-gst_aggregator_release_pad (GstElement * element, GstPad * pad)
-{
- GstAggregator *self = GST_AGGREGATOR (element);
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- GST_INFO_OBJECT (pad, "Removing pad");
-
- SRC_LOCK (self);
- gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, TRUE);
- gst_buffer_replace (&aggpad->priv->peeked_buffer, NULL);
- gst_element_remove_pad (element, pad);
-
- self->priv->has_peer_latency = FALSE;
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
-}
-
-static GstAggregatorPad *
-gst_aggregator_default_create_new_pad (GstAggregator * self,
- GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
-{
- GstAggregatorPad *agg_pad;
- GstAggregatorPrivate *priv = self->priv;
- gint serial = 0;
- gchar *name = NULL;
- GType pad_type =
- GST_PAD_TEMPLATE_GTYPE (templ) ==
- G_TYPE_NONE ? GST_TYPE_AGGREGATOR_PAD : GST_PAD_TEMPLATE_GTYPE (templ);
-
- if (templ->direction != GST_PAD_SINK)
- goto not_sink;
-
- if (templ->presence != GST_PAD_REQUEST)
- goto not_request;
-
- GST_OBJECT_LOCK (self);
- if (req_name == NULL || strlen (req_name) < 6
- || !g_str_has_prefix (req_name, "sink_")
- || strrchr (req_name, '%') != NULL) {
- /* no name given when requesting the pad, use next available int */
- serial = ++priv->max_padserial;
- } else {
- gchar *endptr = NULL;
-
- /* parse serial number from requested padname */
- serial = g_ascii_strtoull (&req_name[5], &endptr, 10);
- if (endptr != NULL && *endptr == '\0') {
- if (serial > priv->max_padserial) {
- priv->max_padserial = serial;
- }
- } else {
- serial = ++priv->max_padserial;
- }
- }
-
- name = g_strdup_printf ("sink_%u", serial);
- g_assert (g_type_is_a (pad_type, GST_TYPE_AGGREGATOR_PAD));
- agg_pad = g_object_new (pad_type,
- "name", name, "direction", GST_PAD_SINK, "template", templ, NULL);
- g_free (name);
-
- GST_OBJECT_UNLOCK (self);
-
- return agg_pad;
-
- /* errors */
-not_sink:
- {
- GST_WARNING_OBJECT (self, "request new pad that is not a SINK pad");
- return NULL;
- }
-not_request:
- {
- GST_WARNING_OBJECT (self, "request new pad that is not a REQUEST pad");
- return NULL;
- }
-}
-
-static GstPad *
-gst_aggregator_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
-{
- GstAggregator *self;
- GstAggregatorPad *agg_pad;
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (element);
- GstAggregatorPrivate *priv = GST_AGGREGATOR (element)->priv;
-
- self = GST_AGGREGATOR (element);
-
- agg_pad = klass->create_new_pad (self, templ, req_name, caps);
- if (!agg_pad) {
- GST_ERROR_OBJECT (element, "Couldn't create new pad");
- return NULL;
- }
-
- GST_DEBUG_OBJECT (element, "Adding pad %s", GST_PAD_NAME (agg_pad));
-
- if (priv->running)
- gst_pad_set_active (GST_PAD (agg_pad), TRUE);
-
- /* add the pad to the element */
- gst_element_add_pad (element, GST_PAD (agg_pad));
-
- return GST_PAD (agg_pad);
-}
-
-/* Must be called with SRC_LOCK held, temporarily releases it! */
-
-static gboolean
-gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
-{
- gboolean query_ret, live;
- GstClockTime our_latency, min, max;
-
- /* Temporarily release the lock to do the query. */
- SRC_UNLOCK (self);
- query_ret = gst_pad_query_default (self->srcpad, GST_OBJECT (self), query);
- SRC_LOCK (self);
-
- if (!query_ret) {
- GST_WARNING_OBJECT (self, "Latency query failed");
- return FALSE;
- }
-
- gst_query_parse_latency (query, &live, &min, &max);
-
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (min))) {
- GST_ERROR_OBJECT (self, "Invalid minimum latency %" GST_TIME_FORMAT
- ". Please file a bug at " PACKAGE_BUGREPORT ".", GST_TIME_ARGS (min));
- return FALSE;
- }
-
- if (self->priv->upstream_latency_min > min) {
- GstClockTimeDiff diff =
- GST_CLOCK_DIFF (min, self->priv->upstream_latency_min);
-
- min += diff;
- if (GST_CLOCK_TIME_IS_VALID (max)) {
- max += diff;
- }
- }
-
- if (min > max && GST_CLOCK_TIME_IS_VALID (max)) {
- SRC_UNLOCK (self);
- GST_ELEMENT_WARNING (self, CORE, CLOCK, (NULL),
- ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %"
- GST_TIME_FORMAT ". Add queues or other buffering elements.",
- GST_TIME_ARGS (max), GST_TIME_ARGS (min)));
- SRC_LOCK (self);
- return FALSE;
- }
-
- our_latency = self->priv->latency;
-
- self->priv->peer_latency_live = live;
- self->priv->peer_latency_min = min;
- self->priv->peer_latency_max = max;
- self->priv->has_peer_latency = TRUE;
-
- /* add our own */
- min += our_latency;
- min += self->priv->sub_latency_min;
- if (GST_CLOCK_TIME_IS_VALID (self->priv->sub_latency_max)
- && GST_CLOCK_TIME_IS_VALID (max))
- max += self->priv->sub_latency_max + our_latency;
- else
- max = GST_CLOCK_TIME_NONE;
-
- SRC_BROADCAST (self);
-
- GST_DEBUG_OBJECT (self, "configured latency live:%s min:%" G_GINT64_FORMAT
- " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max);
-
- gst_query_set_latency (query, live, min, max);
-
- return query_ret;
-}
-
-/*
- * MUST be called with the src_lock held. Temporarily releases the lock inside
- * gst_aggregator_query_latency_unlocked() to do the actual query!
- *
- * See gst_aggregator_get_latency() for doc
- */
-static GstClockTime
-gst_aggregator_get_latency_unlocked (GstAggregator * self)
-{
- GstClockTime latency;
-
- g_return_val_if_fail (GST_IS_AGGREGATOR (self), 0);
-
- if (!self->priv->has_peer_latency) {
- GstQuery *query = gst_query_new_latency ();
- gboolean ret;
-
- ret = gst_aggregator_query_latency_unlocked (self, query);
- gst_query_unref (query);
- if (!ret)
- return GST_CLOCK_TIME_NONE;
- }
-
- if (!self->priv->has_peer_latency || !self->priv->peer_latency_live)
- return GST_CLOCK_TIME_NONE;
-
- /* latency_min is never GST_CLOCK_TIME_NONE by construction */
- latency = self->priv->peer_latency_min;
-
- /* add our own */
- latency += self->priv->latency;
- latency += self->priv->sub_latency_min;
-
- return latency;
-}
-
-/**
- * gst_aggregator_get_latency:
- * @self: a #GstAggregator
- *
- * Retrieves the latency values reported by @self in response to the latency
- * query, or %GST_CLOCK_TIME_NONE if there is not live source connected and the element
- * will not wait for the clock.
- *
- * Typically only called by subclasses.
- *
- * Returns: The latency or %GST_CLOCK_TIME_NONE if the element does not sync
- */
-GstClockTime
-gst_aggregator_get_latency (GstAggregator * self)
-{
- GstClockTime ret;
-
- SRC_LOCK (self);
- ret = gst_aggregator_get_latency_unlocked (self);
- SRC_UNLOCK (self);
-
- return ret;
-}
-
-static gboolean
-gst_aggregator_send_event (GstElement * element, GstEvent * event)
-{
- GstAggregator *self = GST_AGGREGATOR (element);
-
- GST_STATE_LOCK (element);
- if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK &&
- GST_STATE (element) < GST_STATE_PAUSED) {
- gdouble rate;
- GstFormat fmt;
- GstSeekFlags flags;
- GstSeekType start_type, stop_type;
- gint64 start, stop;
-
- gst_event_parse_seek (event, &rate, &fmt, &flags, &start_type,
- &start, &stop_type, &stop);
-
- GST_OBJECT_LOCK (self);
- gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt,
- flags, start_type, start, stop_type, stop, NULL);
- self->priv->next_seqnum = gst_event_get_seqnum (event);
- self->priv->first_buffer = FALSE;
- GST_OBJECT_UNLOCK (self);
-
- GST_DEBUG_OBJECT (element, "Storing segment %" GST_PTR_FORMAT, event);
- }
- GST_STATE_UNLOCK (element);
-
- return GST_ELEMENT_CLASS (aggregator_parent_class)->send_event (element,
- event);
-}
-
-static gboolean
-gst_aggregator_default_src_query (GstAggregator * self, GstQuery * query)
-{
- gboolean res = TRUE;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_SEEKING:
- {
- GstFormat format;
-
- /* don't pass it along as some (file)sink might claim it does
- * whereas with a collectpads in between that will not likely work */
- gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
- gst_query_set_seeking (query, format, FALSE, 0, -1);
- res = TRUE;
-
- break;
- }
- case GST_QUERY_LATENCY:
- SRC_LOCK (self);
- res = gst_aggregator_query_latency_unlocked (self, query);
- SRC_UNLOCK (self);
- break;
- default:
- return gst_pad_query_default (self->srcpad, GST_OBJECT (self), query);
- }
-
- return res;
-}
-
-static gboolean
-gst_aggregator_event_forward_func (GstPad * pad, gpointer user_data)
-{
- EventData *evdata = user_data;
- gboolean ret = TRUE;
- GstPad *peer = gst_pad_get_peer (pad);
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- if (peer) {
- if (evdata->only_to_active_pads && aggpad->priv->first_buffer) {
- GST_DEBUG_OBJECT (pad, "not sending event to inactive pad");
- ret = TRUE;
- } else {
- ret = gst_pad_send_event (peer, gst_event_ref (evdata->event));
- GST_DEBUG_OBJECT (pad, "return of event push is %d", ret);
- }
- }
-
- if (ret == FALSE) {
- if (GST_EVENT_TYPE (evdata->event) == GST_EVENT_SEEK) {
- GstQuery *seeking = gst_query_new_seeking (GST_FORMAT_TIME);
-
- GST_DEBUG_OBJECT (pad, "Event %" GST_PTR_FORMAT " failed", evdata->event);
-
- if (gst_pad_query (peer, seeking)) {
- gboolean seekable;
-
- gst_query_parse_seeking (seeking, NULL, &seekable, NULL, NULL);
-
- if (seekable == FALSE) {
- GST_INFO_OBJECT (pad,
- "Source not seekable, We failed but it does not matter!");
-
- ret = TRUE;
- }
- } else {
- GST_ERROR_OBJECT (pad, "Query seeking FAILED");
- }
-
- gst_query_unref (seeking);
- }
- } else {
- evdata->one_actually_seeked = TRUE;
- }
-
- evdata->result &= ret;
-
- if (peer)
- gst_object_unref (peer);
-
- /* Always send to all pads */
- return FALSE;
-}
-
-static void
-gst_aggregator_forward_event_to_all_sinkpads (GstAggregator * self,
- EventData * evdata)
-{
- evdata->result = TRUE;
- evdata->one_actually_seeked = FALSE;
-
- gst_pad_forward (self->srcpad, gst_aggregator_event_forward_func, evdata);
-
- gst_event_unref (evdata->event);
-}
-
-static gboolean
-gst_aggregator_do_seek (GstAggregator * self, GstEvent * event)
-{
- gdouble rate;
- GstFormat fmt;
- GstSeekFlags flags;
- GstSeekType start_type, stop_type;
- gint64 start, stop;
- gboolean flush;
- EventData evdata = { 0, };
- GstAggregatorPrivate *priv = self->priv;
-
- gst_event_parse_seek (event, &rate, &fmt, &flags, &start_type,
- &start, &stop_type, &stop);
-
- GST_INFO_OBJECT (self, "starting SEEK");
-
- flush = flags & GST_SEEK_FLAG_FLUSH;
-
- GST_OBJECT_LOCK (self);
-
- if (gst_event_get_seqnum (event) == self->priv->next_seqnum) {
- evdata.result = TRUE;
- GST_DEBUG_OBJECT (self, "Dropping duplicated seek event with seqnum %d",
- self->priv->next_seqnum);
- GST_OBJECT_UNLOCK (self);
- goto done;
- }
-
- self->priv->next_seqnum = gst_event_get_seqnum (event);
-
- gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt,
- flags, start_type, start, stop_type, stop, NULL);
-
- /* Seeking sets a position */
- self->priv->first_buffer = FALSE;
-
- if (flush)
- priv->flushing = TRUE;
-
- GST_OBJECT_UNLOCK (self);
-
- if (flush) {
- GstEvent *event = gst_event_new_flush_start ();
-
- gst_event_set_seqnum (event, self->priv->next_seqnum);
- gst_aggregator_stop_srcpad_task (self, event);
- }
-
- /* forward the seek upstream */
- evdata.event = event;
- evdata.flush = flush;
- evdata.only_to_active_pads = FALSE;
- gst_aggregator_forward_event_to_all_sinkpads (self, &evdata);
- event = NULL;
-
- if (!evdata.result || !evdata.one_actually_seeked) {
- GST_OBJECT_LOCK (self);
- priv->flushing = FALSE;
- GST_OBJECT_UNLOCK (self);
-
- /* No flush stop is inbound for us to forward */
- if (flush) {
- GstEvent *event = gst_event_new_flush_stop (TRUE);
-
- gst_event_set_seqnum (event, self->priv->next_seqnum);
- gst_pad_push_event (self->srcpad, event);
- }
- }
-
-done:
- GST_INFO_OBJECT (self, "seek done, result: %d", evdata.result);
-
- return evdata.result;
-}
-
-static gboolean
-gst_aggregator_default_src_event (GstAggregator * self, GstEvent * event)
-{
- EventData evdata = { 0, };
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- /* _do_seek() unrefs the event. */
- return gst_aggregator_do_seek (self, event);
- case GST_EVENT_NAVIGATION:
- /* navigation is rather pointless. */
- gst_event_unref (event);
- return FALSE;
- default:
- break;
- }
-
- /* Don't forward QOS events to pads that had no active buffer yet. Otherwise
- * they will receive a QOS event that has earliest_time=0 (because we can't
- * have negative timestamps), and consider their buffer as too late */
- evdata.event = event;
- evdata.flush = FALSE;
- evdata.only_to_active_pads = GST_EVENT_TYPE (event) == GST_EVENT_QOS;
- gst_aggregator_forward_event_to_all_sinkpads (self, &evdata);
- return evdata.result;
-}
-
-static gboolean
-gst_aggregator_src_pad_event_func (GstPad * pad, GstObject * parent,
- GstEvent * event)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
-
- return klass->src_event (GST_AGGREGATOR (parent), event);
-}
-
-static gboolean
-gst_aggregator_src_pad_query_func (GstPad * pad, GstObject * parent,
- GstQuery * query)
-{
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
-
- return klass->src_query (GST_AGGREGATOR (parent), query);
-}
-
-static gboolean
-gst_aggregator_src_pad_activate_mode_func (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active)
-{
- GstAggregator *self = GST_AGGREGATOR (parent);
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
-
- if (klass->src_activate) {
- if (klass->src_activate (self, mode, active) == FALSE) {
- return FALSE;
- }
- }
-
- if (active == TRUE) {
- switch (mode) {
- case GST_PAD_MODE_PUSH:
- {
- GST_INFO_OBJECT (pad, "Activating pad!");
- gst_aggregator_start_srcpad_task (self);
- return TRUE;
- }
- default:
- {
- GST_ERROR_OBJECT (pad, "Only supported mode is PUSH");
- return FALSE;
- }
- }
- }
-
- /* deactivating */
- GST_INFO_OBJECT (self, "Deactivating srcpad");
-
- gst_aggregator_stop_srcpad_task (self, FALSE);
-
- return TRUE;
-}
-
-static gboolean
-gst_aggregator_default_sink_query (GstAggregator * self,
- GstAggregatorPad * aggpad, GstQuery * query)
-{
- GstPad *pad = GST_PAD (aggpad);
-
- if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) {
- GstQuery *decide_query = NULL;
- GstAggregatorClass *agg_class;
- gboolean ret;
-
- GST_OBJECT_LOCK (self);
- PAD_LOCK (aggpad);
- if (G_UNLIKELY (!aggpad->priv->negotiated)) {
- GST_DEBUG_OBJECT (self,
- "not negotiated yet, can't answer ALLOCATION query");
- PAD_UNLOCK (aggpad);
- GST_OBJECT_UNLOCK (self);
-
- return FALSE;
- }
-
- if ((decide_query = self->priv->allocation_query))
- gst_query_ref (decide_query);
- PAD_UNLOCK (aggpad);
- GST_OBJECT_UNLOCK (self);
-
- GST_DEBUG_OBJECT (self,
- "calling propose allocation with query %" GST_PTR_FORMAT, decide_query);
-
- agg_class = GST_AGGREGATOR_GET_CLASS (self);
-
- /* pass the query to the propose_allocation vmethod if any */
- if (agg_class->propose_allocation)
- ret = agg_class->propose_allocation (self, aggpad, decide_query, query);
- else
- ret = FALSE;
-
- if (decide_query)
- gst_query_unref (decide_query);
-
- GST_DEBUG_OBJECT (self, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query);
- return ret;
- }
-
- return gst_pad_query_default (pad, GST_OBJECT (self), query);
-}
-
-static gboolean
-gst_aggregator_default_sink_query_pre_queue (GstAggregator * self,
- GstAggregatorPad * aggpad, GstQuery * query)
-{
- if (GST_QUERY_IS_SERIALIZED (query)) {
- GstStructure *s;
- gboolean ret = FALSE;
-
- SRC_LOCK (self);
- PAD_LOCK (aggpad);
-
- if (aggpad->priv->flow_return != GST_FLOW_OK) {
- SRC_UNLOCK (self);
- goto flushing;
- }
-
- g_queue_push_head (&aggpad->priv->data, query);
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
-
- while (!gst_aggregator_pad_queue_is_empty (aggpad)
- && aggpad->priv->flow_return == GST_FLOW_OK) {
- GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
- PAD_WAIT_EVENT (aggpad);
- }
-
- s = gst_query_writable_structure (query);
- if (gst_structure_get_boolean (s, "gst-aggregator-retval", &ret))
- gst_structure_remove_field (s, "gst-aggregator-retval");
- else
- g_queue_remove (&aggpad->priv->data, query);
-
- if (aggpad->priv->flow_return != GST_FLOW_OK)
- goto flushing;
-
- PAD_UNLOCK (aggpad);
-
- return ret;
- } else {
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
-
- return klass->sink_query (self, aggpad, query);
- }
-
-flushing:
- GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query",
- gst_flow_get_name (aggpad->priv->flow_return));
- PAD_UNLOCK (aggpad);
-
- return FALSE;
-}
-
-static void
-gst_aggregator_finalize (GObject * object)
-{
- GstAggregator *self = (GstAggregator *) object;
-
- g_mutex_clear (&self->priv->src_lock);
- g_cond_clear (&self->priv->src_cond);
-
- G_OBJECT_CLASS (aggregator_parent_class)->finalize (object);
-}
-
-/*
- * gst_aggregator_set_latency_property:
- * @agg: a #GstAggregator
- * @latency: the new latency value (in nanoseconds).
- *
- * Sets the new latency value to @latency. This value is used to limit the
- * amount of time a pad waits for data to appear before considering the pad
- * as unresponsive.
- */
-static void
-gst_aggregator_set_latency_property (GstAggregator * self, GstClockTime latency)
-{
- gboolean changed;
-
- g_return_if_fail (GST_IS_AGGREGATOR (self));
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (latency));
-
- SRC_LOCK (self);
- changed = (self->priv->latency != latency);
-
- if (changed) {
- GList *item;
-
- GST_OBJECT_LOCK (self);
- /* First lock all the pads */
- for (item = GST_ELEMENT_CAST (self)->sinkpads; item; item = item->next) {
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data);
- PAD_LOCK (aggpad);
- }
-
- self->priv->latency = latency;
-
- SRC_BROADCAST (self);
-
- /* Now wake up the pads */
- for (item = GST_ELEMENT_CAST (self)->sinkpads; item; item = item->next) {
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data);
- PAD_BROADCAST_EVENT (aggpad);
- PAD_UNLOCK (aggpad);
- }
- GST_OBJECT_UNLOCK (self);
- }
-
- SRC_UNLOCK (self);
-
- if (changed)
- gst_element_post_message (GST_ELEMENT_CAST (self),
- gst_message_new_latency (GST_OBJECT_CAST (self)));
-}
-
-/*
- * gst_aggregator_get_latency_property:
- * @agg: a #GstAggregator
- *
- * Gets the latency value. See gst_aggregator_set_latency for
- * more details.
- *
- * Returns: The time in nanoseconds to wait for data to arrive on a sink pad
- * before a pad is deemed unresponsive. A value of -1 means an
- * unlimited time.
- */
-static GstClockTime
-gst_aggregator_get_latency_property (GstAggregator * agg)
-{
- GstClockTime res;
-
- g_return_val_if_fail (GST_IS_AGGREGATOR (agg), GST_CLOCK_TIME_NONE);
-
- GST_OBJECT_LOCK (agg);
- res = agg->priv->latency;
- GST_OBJECT_UNLOCK (agg);
-
- return res;
-}
-
-static void
-gst_aggregator_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAggregator *agg = GST_AGGREGATOR (object);
-
- switch (prop_id) {
- case PROP_LATENCY:
- gst_aggregator_set_latency_property (agg, g_value_get_uint64 (value));
- break;
- case PROP_MIN_UPSTREAM_LATENCY:
- SRC_LOCK (agg);
- agg->priv->upstream_latency_min = g_value_get_uint64 (value);
- SRC_UNLOCK (agg);
- break;
- case PROP_START_TIME_SELECTION:
- agg->priv->start_time_selection = g_value_get_enum (value);
- break;
- case PROP_START_TIME:
- agg->priv->start_time = g_value_get_uint64 (value);
- break;
- case PROP_EMIT_SIGNALS:
- agg->priv->emit_signals = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_aggregator_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAggregator *agg = GST_AGGREGATOR (object);
-
- switch (prop_id) {
- case PROP_LATENCY:
- g_value_set_uint64 (value, gst_aggregator_get_latency_property (agg));
- break;
- case PROP_MIN_UPSTREAM_LATENCY:
- SRC_LOCK (agg);
- g_value_set_uint64 (value, agg->priv->upstream_latency_min);
- SRC_UNLOCK (agg);
- break;
- case PROP_START_TIME_SELECTION:
- g_value_set_enum (value, agg->priv->start_time_selection);
- break;
- case PROP_START_TIME:
- g_value_set_uint64 (value, agg->priv->start_time);
- break;
- case PROP_EMIT_SIGNALS:
- g_value_set_boolean (value, agg->priv->emit_signals);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* GObject vmethods implementations */
-static void
-gst_aggregator_class_init (GstAggregatorClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
- GstElementClass *gstelement_class = (GstElementClass *) klass;
-
- aggregator_parent_class = g_type_class_peek_parent (klass);
-
- GST_DEBUG_CATEGORY_INIT (aggregator_debug, "aggregator",
- GST_DEBUG_FG_MAGENTA, "GstAggregator");
-
- if (aggregator_private_offset != 0)
- g_type_class_adjust_private_offset (klass, &aggregator_private_offset);
-
- klass->finish_buffer = gst_aggregator_default_finish_buffer;
- klass->finish_buffer_list = gst_aggregator_default_finish_buffer_list;
-
- klass->sink_event = gst_aggregator_default_sink_event;
- klass->sink_query = gst_aggregator_default_sink_query;
-
- klass->src_event = gst_aggregator_default_src_event;
- klass->src_query = gst_aggregator_default_src_query;
-
- klass->create_new_pad = gst_aggregator_default_create_new_pad;
- klass->update_src_caps = gst_aggregator_default_update_src_caps;
- klass->fixate_src_caps = gst_aggregator_default_fixate_src_caps;
- klass->negotiated_src_caps = gst_aggregator_default_negotiated_src_caps;
-
- klass->negotiate = gst_aggregator_default_negotiate;
-
- klass->sink_event_pre_queue = gst_aggregator_default_sink_event_pre_queue;
- klass->sink_query_pre_queue = gst_aggregator_default_sink_query_pre_queue;
-
- gstelement_class->request_new_pad =
- GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
- gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aggregator_send_event);
- gstelement_class->release_pad =
- GST_DEBUG_FUNCPTR (gst_aggregator_release_pad);
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_aggregator_change_state);
-
- gobject_class->set_property = gst_aggregator_set_property;
- gobject_class->get_property = gst_aggregator_get_property;
- gobject_class->finalize = gst_aggregator_finalize;
-
- g_object_class_install_property (gobject_class, PROP_LATENCY,
- g_param_spec_uint64 ("latency", "Buffer latency",
- "Additional latency in live mode to allow upstream "
- "to take longer to produce buffers for the current "
- "position (in nanoseconds)", 0, G_MAXUINT64,
- DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstAggregator:min-upstream-latency:
- *
- * Force minimum upstream latency (in nanoseconds). When sources with a
- * higher latency are expected to be plugged in dynamically after the
- * aggregator has started playing, this allows overriding the minimum
- * latency reported by the initial source(s). This is only taken into
- * account when larger than the actually reported minimum latency.
- *
- * Since: 1.16
- */
- g_object_class_install_property (gobject_class, PROP_MIN_UPSTREAM_LATENCY,
- g_param_spec_uint64 ("min-upstream-latency", "Buffer latency",
- "When sources with a higher latency are expected to be plugged "
- "in dynamically after the aggregator has started playing, "
- "this allows overriding the minimum latency reported by the "
- "initial source(s). This is only taken into account when larger "
- "than the actually reported minimum latency. (nanoseconds)",
- 0, G_MAXUINT64,
- DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_START_TIME_SELECTION,
- g_param_spec_enum ("start-time-selection", "Start Time Selection",
- "Decides which start time is output",
- gst_aggregator_start_time_selection_get_type (),
- DEFAULT_START_TIME_SELECTION,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_START_TIME,
- g_param_spec_uint64 ("start-time", "Start Time",
- "Start time to use if start-time-selection=set", 0,
- G_MAXUINT64,
- DEFAULT_START_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstAggregator:emit-signals:
- *
- * Enables the emission of signals such as #GstAggregator::samples-selected
- *
- * Since: 1.18
- */
- g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
- g_param_spec_boolean ("emit-signals", "Emit signals",
- "Send signals", DEFAULT_EMIT_SIGNALS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstAggregator::samples-selected:
- * @aggregator: The #GstAggregator that emitted the signal
- * @segment: The #GstSegment the next output buffer is part of
- * @pts: The presentation timestamp of the next output buffer
- * @dts: The decoding timestamp of the next output buffer
- * @duration: The duration of the next output buffer
- * @info: (nullable): a #GstStructure containing additional information
- *
- * Signals that the #GstAggregator subclass has selected the next set
- * of input samples it will aggregate. Handlers may call
- * gst_aggregator_peek_next_sample() at that point.
- *
- * Since: 1.18
- */
- gst_aggregator_signals[SIGNAL_SAMPLES_SELECTED] =
- g_signal_new ("samples-selected", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 5,
- GST_TYPE_SEGMENT | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_CLOCK_TIME,
- GST_TYPE_CLOCK_TIME, GST_TYPE_CLOCK_TIME,
- GST_TYPE_STRUCTURE | G_SIGNAL_TYPE_STATIC_SCOPE);
-}
-
-static inline gpointer
-gst_aggregator_get_instance_private (GstAggregator * self)
-{
- return (G_STRUCT_MEMBER_P (self, aggregator_private_offset));
-}
-
-static void
-gst_aggregator_init (GstAggregator * self, GstAggregatorClass * klass)
-{
- GstPadTemplate *pad_template;
- GstAggregatorPrivate *priv;
- GType pad_type;
-
- g_return_if_fail (klass->aggregate != NULL);
-
- self->priv = gst_aggregator_get_instance_private (self);
-
- priv = self->priv;
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
- g_return_if_fail (pad_template != NULL);
-
- priv->max_padserial = -1;
- priv->tags_changed = FALSE;
-
- self->priv->peer_latency_live = FALSE;
- self->priv->peer_latency_min = self->priv->sub_latency_min = 0;
- self->priv->peer_latency_max = self->priv->sub_latency_max = 0;
- self->priv->has_peer_latency = FALSE;
-
- pad_type =
- GST_PAD_TEMPLATE_GTYPE (pad_template) ==
- G_TYPE_NONE ? GST_TYPE_AGGREGATOR_PAD :
- GST_PAD_TEMPLATE_GTYPE (pad_template);
- g_assert (g_type_is_a (pad_type, GST_TYPE_AGGREGATOR_PAD));
- self->srcpad =
- g_object_new (pad_type, "name", "src", "direction", GST_PAD_SRC,
- "template", pad_template, NULL);
-
- gst_aggregator_reset_flow_values (self);
-
- gst_pad_set_event_function (self->srcpad,
- GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_event_func));
- gst_pad_set_query_function (self->srcpad,
- GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_query_func));
- gst_pad_set_activatemode_function (self->srcpad,
- GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_activate_mode_func));
-
- gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
-
- self->priv->upstream_latency_min = DEFAULT_MIN_UPSTREAM_LATENCY;
- self->priv->latency = DEFAULT_LATENCY;
- self->priv->start_time_selection = DEFAULT_START_TIME_SELECTION;
- self->priv->start_time = DEFAULT_START_TIME;
-
- g_mutex_init (&self->priv->src_lock);
- g_cond_init (&self->priv->src_cond);
-}
-
-/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
- * method to get to the padtemplates */
-GType
-gst_aggregator_get_type (void)
-{
- static gsize type = 0;
-
- if (g_once_init_enter (&type)) {
- GType _type;
- static const GTypeInfo info = {
- sizeof (GstAggregatorClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_aggregator_class_init,
- NULL,
- NULL,
- sizeof (GstAggregator),
- 0,
- (GInstanceInitFunc) gst_aggregator_init,
- };
-
- _type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstAggregator", &info, G_TYPE_FLAG_ABSTRACT);
-
- aggregator_private_offset =
- g_type_add_instance_private (_type, sizeof (GstAggregatorPrivate));
-
- g_once_init_leave (&type, _type);
- }
- return type;
-}
-
-/* Must be called with SRC lock and PAD lock held */
-static gboolean
-gst_aggregator_pad_has_space (GstAggregator * self, GstAggregatorPad * aggpad)
-{
- guint64 max_time_level;
-
- /* Empty queue always has space */
- if (aggpad->priv->num_buffers == 0 && aggpad->priv->clipped_buffer == NULL)
- return TRUE;
-
- /* We also want at least two buffers, one is being processed and one is ready
- * for the next iteration when we operate in live mode. */
- if (self->priv->peer_latency_live && aggpad->priv->num_buffers < 2)
- return TRUE;
-
- /* zero latency, if there is a buffer, it's full */
- if (self->priv->latency == 0)
- return FALSE;
-
- /* On top of our latency, we also want to allow buffering up to the
- * minimum upstream latency to allow queue free sources with lower then
- * upstream latency. */
- max_time_level = self->priv->latency + self->priv->upstream_latency_min;
-
- /* Allow no more buffers than the latency */
- return (aggpad->priv->time_level <= max_time_level);
-}
-
-/* Must be called with the PAD_LOCK held */
-static void
-apply_buffer (GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head)
-{
- GstClockTime timestamp;
-
- if (GST_BUFFER_DTS_IS_VALID (buffer))
- timestamp = GST_BUFFER_DTS (buffer);
- else
- timestamp = GST_BUFFER_PTS (buffer);
-
- if (timestamp == GST_CLOCK_TIME_NONE) {
- if (head)
- timestamp = aggpad->priv->head_position;
- else
- timestamp = aggpad->priv->tail_position;
- }
-
- /* add duration */
- if (GST_BUFFER_DURATION_IS_VALID (buffer))
- timestamp += GST_BUFFER_DURATION (buffer);
-
- if (head)
- aggpad->priv->head_position = timestamp;
- else
- aggpad->priv->tail_position = timestamp;
-
- update_time_level (aggpad, head);
-}
-
-/*
- * Can be called either from the sinkpad's chain function or from the srcpad's
- * thread in the case of a buffer synthetized from a GAP event.
- * Because of this second case, FLUSH_LOCK can't be used here.
- */
-
-static GstFlowReturn
-gst_aggregator_pad_chain_internal (GstAggregator * self,
- GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head)
-{
- GstFlowReturn flow_return;
- GstClockTime buf_pts;
-
- PAD_LOCK (aggpad);
- flow_return = aggpad->priv->flow_return;
- if (flow_return != GST_FLOW_OK)
- goto flushing;
-
- PAD_UNLOCK (aggpad);
-
- buf_pts = GST_BUFFER_PTS (buffer);
-
- for (;;) {
- SRC_LOCK (self);
- GST_OBJECT_LOCK (self);
- PAD_LOCK (aggpad);
-
- if (aggpad->priv->first_buffer) {
- self->priv->has_peer_latency = FALSE;
- aggpad->priv->first_buffer = FALSE;
- }
-
- if ((gst_aggregator_pad_has_space (self, aggpad) || !head)
- && aggpad->priv->flow_return == GST_FLOW_OK) {
- if (head)
- g_queue_push_head (&aggpad->priv->data, buffer);
- else
- g_queue_push_tail (&aggpad->priv->data, buffer);
- apply_buffer (aggpad, buffer, head);
- aggpad->priv->num_buffers++;
- buffer = NULL;
- SRC_BROADCAST (self);
- break;
- }
-
- flow_return = aggpad->priv->flow_return;
- if (flow_return != GST_FLOW_OK) {
- GST_OBJECT_UNLOCK (self);
- SRC_UNLOCK (self);
- goto flushing;
- }
- GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
- GST_OBJECT_UNLOCK (self);
- SRC_UNLOCK (self);
- PAD_WAIT_EVENT (aggpad);
-
- PAD_UNLOCK (aggpad);
- }
-
- if (self->priv->first_buffer) {
- GstClockTime start_time;
- GstAggregatorPad *srcpad = GST_AGGREGATOR_PAD (self->srcpad);
-
- switch (self->priv->start_time_selection) {
- case GST_AGGREGATOR_START_TIME_SELECTION_ZERO:
- default:
- start_time = 0;
- break;
- case GST_AGGREGATOR_START_TIME_SELECTION_FIRST:
- GST_OBJECT_LOCK (aggpad);
- if (aggpad->priv->head_segment.format == GST_FORMAT_TIME) {
- start_time = buf_pts;
- if (start_time != -1) {
- start_time = MAX (start_time, aggpad->priv->head_segment.start);
- start_time =
- gst_segment_to_running_time (&aggpad->priv->head_segment,
- GST_FORMAT_TIME, start_time);
- }
- } else {
- start_time = 0;
- GST_WARNING_OBJECT (aggpad,
- "Ignoring request of selecting the first start time "
- "as the segment is a %s segment instead of a time segment",
- gst_format_get_name (aggpad->segment.format));
- }
- GST_OBJECT_UNLOCK (aggpad);
- break;
- case GST_AGGREGATOR_START_TIME_SELECTION_SET:
- start_time = self->priv->start_time;
- if (start_time == -1)
- start_time = 0;
- break;
- }
-
- if (start_time != -1) {
- if (srcpad->segment.position == -1)
- srcpad->segment.position = start_time;
- else
- srcpad->segment.position = MIN (start_time, srcpad->segment.position);
-
- GST_DEBUG_OBJECT (self, "Selecting start time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start_time));
- }
- }
-
- PAD_UNLOCK (aggpad);
- GST_OBJECT_UNLOCK (self);
- SRC_UNLOCK (self);
-
- GST_DEBUG_OBJECT (aggpad, "Done chaining");
-
- return flow_return;
-
-flushing:
- PAD_UNLOCK (aggpad);
-
- GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping buffer",
- gst_flow_get_name (flow_return));
- if (buffer)
- gst_buffer_unref (buffer);
-
- return flow_return;
-}
-
-static GstFlowReturn
-gst_aggregator_pad_chain (GstPad * pad, GstObject * object, GstBuffer * buffer)
-{
- GstFlowReturn ret;
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- PAD_FLUSH_LOCK (aggpad);
-
- ret = gst_aggregator_pad_chain_internal (GST_AGGREGATOR_CAST (object),
- aggpad, buffer, TRUE);
-
- PAD_FLUSH_UNLOCK (aggpad);
-
- return ret;
-}
-
-static gboolean
-gst_aggregator_pad_query_func (GstPad * pad, GstObject * parent,
- GstQuery * query)
-{
- GstAggregator *self = GST_AGGREGATOR (parent);
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- g_assert (klass->sink_query_pre_queue);
- return klass->sink_query_pre_queue (self, aggpad, query);
-}
-
-static GstFlowReturn
-gst_aggregator_pad_event_func (GstPad * pad, GstObject * parent,
- GstEvent * event)
-{
- GstAggregator *self = GST_AGGREGATOR (parent);
- GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- g_assert (klass->sink_event_pre_queue);
- return klass->sink_event_pre_queue (self, aggpad, event);
-}
-
-static gboolean
-gst_aggregator_pad_activate_mode_func (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active)
-{
- GstAggregator *self = GST_AGGREGATOR (parent);
- GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
-
- if (active == FALSE) {
- SRC_LOCK (self);
- gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, TRUE);
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
- } else {
- PAD_LOCK (aggpad);
- aggpad->priv->flow_return = GST_FLOW_OK;
- PAD_BROADCAST_EVENT (aggpad);
- PAD_UNLOCK (aggpad);
- }
-
- return TRUE;
-}
-
-/***********************************
- * GstAggregatorPad implementation *
- ************************************/
-G_DEFINE_TYPE_WITH_PRIVATE (GstAggregatorPad, gst_aggregator_pad, GST_TYPE_PAD);
-
-#define DEFAULT_PAD_EMIT_SIGNALS FALSE
-
-enum
-{
- PAD_PROP_0,
- PAD_PROP_EMIT_SIGNALS,
-};
-
-enum
-{
- PAD_SIGNAL_BUFFER_CONSUMED,
- PAD_LAST_SIGNAL,
-};
-
-static guint gst_aggregator_pad_signals[PAD_LAST_SIGNAL] = { 0 };
-
-static void
-gst_aggregator_pad_constructed (GObject * object)
-{
- GstPad *pad = GST_PAD (object);
-
- if (GST_PAD_IS_SINK (pad)) {
- gst_pad_set_chain_function (pad,
- GST_DEBUG_FUNCPTR (gst_aggregator_pad_chain));
- gst_pad_set_event_full_function_full (pad,
- GST_DEBUG_FUNCPTR (gst_aggregator_pad_event_func), NULL, NULL);
- gst_pad_set_query_function (pad,
- GST_DEBUG_FUNCPTR (gst_aggregator_pad_query_func));
- gst_pad_set_activatemode_function (pad,
- GST_DEBUG_FUNCPTR (gst_aggregator_pad_activate_mode_func));
- }
-}
-
-static void
-gst_aggregator_pad_finalize (GObject * object)
-{
- GstAggregatorPad *pad = (GstAggregatorPad *) object;
-
- gst_buffer_replace (&pad->priv->peeked_buffer, NULL);
- g_cond_clear (&pad->priv->event_cond);
- g_mutex_clear (&pad->priv->flush_lock);
- g_mutex_clear (&pad->priv->lock);
-
- G_OBJECT_CLASS (gst_aggregator_pad_parent_class)->finalize (object);
-}
-
-static void
-gst_aggregator_pad_dispose (GObject * object)
-{
- GstAggregatorPad *pad = (GstAggregatorPad *) object;
-
- gst_aggregator_pad_set_flushing (pad, GST_FLOW_FLUSHING, TRUE);
-
- G_OBJECT_CLASS (gst_aggregator_pad_parent_class)->dispose (object);
-}
-
-static void
-gst_aggregator_pad_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAggregatorPad *pad = GST_AGGREGATOR_PAD (object);
-
- switch (prop_id) {
- case PAD_PROP_EMIT_SIGNALS:
- pad->priv->emit_signals = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_aggregator_pad_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAggregatorPad *pad = GST_AGGREGATOR_PAD (object);
-
- switch (prop_id) {
- case PAD_PROP_EMIT_SIGNALS:
- g_value_set_boolean (value, pad->priv->emit_signals);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_aggregator_pad_class_init (GstAggregatorPadClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
-
- gobject_class->constructed = gst_aggregator_pad_constructed;
- gobject_class->finalize = gst_aggregator_pad_finalize;
- gobject_class->dispose = gst_aggregator_pad_dispose;
- gobject_class->set_property = gst_aggregator_pad_set_property;
- gobject_class->get_property = gst_aggregator_pad_get_property;
-
- /**
- * GstAggregatorPad:buffer-consumed:
- * @aggregator: The #GstAggregator that emitted the signal
- * @buffer: The buffer that was consumed
- *
- * Signals that a buffer was consumed. As aggregator pads store buffers
- * in an internal queue, there is no direct match between input and output
- * buffers at any given time. This signal can be useful to forward metas
- * such as #GstVideoTimeCodeMeta or #GstVideoCaptionMeta at the right time.
- *
- * Since: 1.16
- */
- gst_aggregator_pad_signals[PAD_SIGNAL_BUFFER_CONSUMED] =
- g_signal_new ("buffer-consumed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
-
- /**
- * GstAggregatorPad:emit-signals:
- *
- * Enables the emission of signals such as #GstAggregatorPad::buffer-consumed
- *
- * Since: 1.16
- */
- g_object_class_install_property (gobject_class, PAD_PROP_EMIT_SIGNALS,
- g_param_spec_boolean ("emit-signals", "Emit signals",
- "Send signals to signal data consumption", DEFAULT_PAD_EMIT_SIGNALS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gst_aggregator_pad_init (GstAggregatorPad * pad)
-{
- pad->priv = gst_aggregator_pad_get_instance_private (pad);
-
- g_queue_init (&pad->priv->data);
- g_cond_init (&pad->priv->event_cond);
-
- g_mutex_init (&pad->priv->flush_lock);
- g_mutex_init (&pad->priv->lock);
-
- gst_aggregator_pad_reset_unlocked (pad);
- pad->priv->negotiated = FALSE;
- pad->priv->emit_signals = DEFAULT_PAD_EMIT_SIGNALS;
-}
-
-/* Must be called with the PAD_LOCK held */
-static void
-gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad, GstBuffer * buffer,
- gboolean dequeued)
-{
- if (dequeued)
- pad->priv->num_buffers--;
-
- if (buffer && pad->priv->emit_signals) {
- g_signal_emit (pad, gst_aggregator_pad_signals[PAD_SIGNAL_BUFFER_CONSUMED],
- 0, buffer);
- }
- PAD_BROADCAST_EVENT (pad);
-}
-
-/* Must be called with the PAD_LOCK held */
-static void
-gst_aggregator_pad_clip_buffer_unlocked (GstAggregatorPad * pad)
-{
- GstAggregator *self = NULL;
- GstAggregatorClass *aggclass = NULL;
- GstBuffer *buffer = NULL;
-
- while (pad->priv->clipped_buffer == NULL &&
- GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) {
- buffer = g_queue_pop_tail (&pad->priv->data);
-
- apply_buffer (pad, buffer, FALSE);
-
- /* We only take the parent here so that it's not taken if the buffer is
- * already clipped or if the queue is empty.
- */
- if (self == NULL) {
- self = GST_AGGREGATOR (gst_pad_get_parent_element (GST_PAD (pad)));
- if (self == NULL) {
- gst_buffer_unref (buffer);
- return;
- }
-
- aggclass = GST_AGGREGATOR_GET_CLASS (self);
- }
-
- if (aggclass->clip) {
- GST_TRACE_OBJECT (pad, "Clipping: %" GST_PTR_FORMAT, buffer);
-
- buffer = aggclass->clip (self, pad, buffer);
-
- if (buffer == NULL) {
- gst_aggregator_pad_buffer_consumed (pad, buffer, TRUE);
- GST_TRACE_OBJECT (pad, "Clipping consumed the buffer");
- }
- }
-
- pad->priv->clipped_buffer = buffer;
- }
-
- if (self)
- gst_object_unref (self);
-}
-
-/**
- * gst_aggregator_pad_pop_buffer:
- * @pad: the pad to get buffer from
- *
- * Steal the ref to the buffer currently queued in @pad.
- *
- * Returns: (nullable) (transfer full): The buffer in @pad or NULL if no buffer was
- * queued. You should unref the buffer after usage.
- */
-GstBuffer *
-gst_aggregator_pad_pop_buffer (GstAggregatorPad * pad)
-{
- GstBuffer *buffer = NULL;
-
- PAD_LOCK (pad);
-
- /* If the subclass has already peeked a buffer, we guarantee
- * that it receives the same buffer, no matter if the pad has
- * errored out / been flushed in the meantime.
- */
- if (pad->priv->peeked_buffer) {
- buffer = pad->priv->peeked_buffer;
- goto done;
- }
-
- if (pad->priv->flow_return != GST_FLOW_OK)
- goto done;
-
- gst_aggregator_pad_clip_buffer_unlocked (pad);
- buffer = pad->priv->clipped_buffer;
-
-done:
- if (buffer) {
- if (pad->priv->clipped_buffer != NULL) {
- /* Here we still hold a reference to both the clipped buffer
- * and possibly the peeked buffer, we transfer the first and
- * potentially release the second
- */
- gst_aggregator_pad_buffer_consumed (pad, buffer, TRUE);
- pad->priv->clipped_buffer = NULL;
- gst_buffer_replace (&pad->priv->peeked_buffer, NULL);
- } else {
- /* Here our clipped buffer has already been released, for
- * example because of a flush. We thus transfer the reference
- * to the peeked buffer to the caller, and we don't decrement
- * pad.num_buffers as it has already been done elsewhere
- */
- gst_aggregator_pad_buffer_consumed (pad, buffer, FALSE);
- pad->priv->peeked_buffer = NULL;
- }
- GST_DEBUG_OBJECT (pad, "Consumed: %" GST_PTR_FORMAT, buffer);
- }
-
- PAD_UNLOCK (pad);
-
- return buffer;
-}
-
-/**
- * gst_aggregator_pad_drop_buffer:
- * @pad: the pad where to drop any pending buffer
- *
- * Drop the buffer currently queued in @pad.
- *
- * Returns: TRUE if there was a buffer queued in @pad, or FALSE if not.
- */
-gboolean
-gst_aggregator_pad_drop_buffer (GstAggregatorPad * pad)
-{
- GstBuffer *buf;
-
- buf = gst_aggregator_pad_pop_buffer (pad);
-
- if (buf == NULL)
- return FALSE;
-
- gst_buffer_unref (buf);
- return TRUE;
-}
-
-/**
- * gst_aggregator_pad_peek_buffer:
- * @pad: the pad to get buffer from
- *
- * Returns: (nullable) (transfer full): A reference to the buffer in @pad or
- * NULL if no buffer was queued. You should unref the buffer after
- * usage.
- */
-GstBuffer *
-gst_aggregator_pad_peek_buffer (GstAggregatorPad * pad)
-{
- GstBuffer *buffer = NULL;
-
- PAD_LOCK (pad);
-
- if (pad->priv->peeked_buffer) {
- buffer = gst_buffer_ref (pad->priv->peeked_buffer);
- goto done;
- }
-
- if (pad->priv->flow_return != GST_FLOW_OK)
- goto done;
-
- gst_aggregator_pad_clip_buffer_unlocked (pad);
-
- if (pad->priv->clipped_buffer) {
- buffer = gst_buffer_ref (pad->priv->clipped_buffer);
- pad->priv->peeked_buffer = gst_buffer_ref (buffer);
- } else {
- buffer = NULL;
- }
-
-done:
- PAD_UNLOCK (pad);
- return buffer;
-}
-
-/**
- * gst_aggregator_pad_has_buffer:
- * @pad: the pad to check the buffer on
- *
- * This checks if a pad has a buffer available that will be returned by
- * a call to gst_aggregator_pad_peek_buffer() or
- * gst_aggregator_pad_pop_buffer().
- *
- * Returns: %TRUE if the pad has a buffer available as the next thing.
- *
- * Since: 1.14.1
- */
-gboolean
-gst_aggregator_pad_has_buffer (GstAggregatorPad * pad)
-{
- gboolean has_buffer;
-
- PAD_LOCK (pad);
-
- if (pad->priv->peeked_buffer) {
- has_buffer = TRUE;
- } else {
- gst_aggregator_pad_clip_buffer_unlocked (pad);
- has_buffer = (pad->priv->clipped_buffer != NULL);
- if (has_buffer)
- pad->priv->peeked_buffer = gst_buffer_ref (pad->priv->clipped_buffer);
- }
- PAD_UNLOCK (pad);
-
- return has_buffer;
-}
-
-/**
- * gst_aggregator_pad_is_eos:
- * @pad: an aggregator pad
- *
- * Returns: %TRUE if the pad is EOS, otherwise %FALSE.
- */
-gboolean
-gst_aggregator_pad_is_eos (GstAggregatorPad * pad)
-{
- gboolean is_eos;
-
- PAD_LOCK (pad);
- is_eos = pad->priv->eos;
- PAD_UNLOCK (pad);
-
- return is_eos;
-}
-
-#if 0
-/*
- * gst_aggregator_merge_tags:
- * @self: a #GstAggregator
- * @tags: a #GstTagList to merge
- * @mode: the #GstTagMergeMode to use
- *
- * Adds tags to so-called pending tags, which will be processed
- * before pushing out data downstream.
- *
- * Note that this is provided for convenience, and the subclass is
- * not required to use this and can still do tag handling on its own.
- *
- * MT safe.
- */
-void
-gst_aggregator_merge_tags (GstAggregator * self,
- const GstTagList * tags, GstTagMergeMode mode)
-{
- GstTagList *otags;
-
- g_return_if_fail (GST_IS_AGGREGATOR (self));
- g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));
-
- /* FIXME Check if we can use OBJECT lock here! */
- GST_OBJECT_LOCK (self);
- if (tags)
- GST_DEBUG_OBJECT (self, "merging tags %" GST_PTR_FORMAT, tags);
- otags = self->priv->tags;
- self->priv->tags = gst_tag_list_merge (self->priv->tags, tags, mode);
- if (otags)
- gst_tag_list_unref (otags);
- self->priv->tags_changed = TRUE;
- GST_OBJECT_UNLOCK (self);
-}
-#endif
-
-/**
- * gst_aggregator_set_latency:
- * @self: a #GstAggregator
- * @min_latency: minimum latency
- * @max_latency: maximum latency
- *
- * Lets #GstAggregator sub-classes tell the baseclass what their internal
- * latency is. Will also post a LATENCY message on the bus so the pipeline
- * can reconfigure its global latency.
- */
-void
-gst_aggregator_set_latency (GstAggregator * self,
- GstClockTime min_latency, GstClockTime max_latency)
-{
- gboolean changed = FALSE;
-
- g_return_if_fail (GST_IS_AGGREGATOR (self));
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
- g_return_if_fail (max_latency >= min_latency);
-
- SRC_LOCK (self);
- if (self->priv->sub_latency_min != min_latency) {
- self->priv->sub_latency_min = min_latency;
- changed = TRUE;
- }
- if (self->priv->sub_latency_max != max_latency) {
- self->priv->sub_latency_max = max_latency;
- changed = TRUE;
- }
-
- if (changed)
- SRC_BROADCAST (self);
- SRC_UNLOCK (self);
-
- if (changed) {
- gst_element_post_message (GST_ELEMENT_CAST (self),
- gst_message_new_latency (GST_OBJECT_CAST (self)));
- }
-}
-
-/**
- * gst_aggregator_get_buffer_pool:
- * @self: a #GstAggregator
- *
- * Returns: (transfer full) (nullable): the instance of the #GstBufferPool used
- * by @trans; free it after use it
- */
-GstBufferPool *
-gst_aggregator_get_buffer_pool (GstAggregator * self)
-{
- GstBufferPool *pool;
-
- g_return_val_if_fail (GST_IS_AGGREGATOR (self), NULL);
-
- GST_OBJECT_LOCK (self);
- pool = self->priv->pool;
- if (pool)
- gst_object_ref (pool);
- GST_OBJECT_UNLOCK (self);
-
- return pool;
-}
-
-/**
- * gst_aggregator_get_allocator:
- * @self: a #GstAggregator
- * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
- * used
- * @params: (out caller-allocates) (optional): the
- * #GstAllocationParams of @allocator
- *
- * Lets #GstAggregator sub-classes get the memory @allocator
- * acquired by the base class and its @params.
- *
- * Unref the @allocator after use it.
- */
-void
-gst_aggregator_get_allocator (GstAggregator * self,
- GstAllocator ** allocator, GstAllocationParams * params)
-{
- g_return_if_fail (GST_IS_AGGREGATOR (self));
-
- if (allocator)
- *allocator = self->priv->allocator ?
- gst_object_ref (self->priv->allocator) : NULL;
-
- if (params)
- *params = self->priv->allocation_params;
-}
-
-/**
- * gst_aggregator_simple_get_next_time:
- * @self: A #GstAggregator
- *
- * This is a simple #GstAggregatorClass::get_next_time implementation that
- * just looks at the #GstSegment on the srcpad of the aggregator and bases
- * the next time on the running time there.
- *
- * This is the desired behaviour in most cases where you have a live source
- * and you have a dead line based aggregator subclass.
- *
- * Returns: The running time based on the position
- *
- * Since: 1.16
- */
-GstClockTime
-gst_aggregator_simple_get_next_time (GstAggregator * self)
-{
- GstClockTime next_time;
- GstAggregatorPad *srcpad = GST_AGGREGATOR_PAD (self->srcpad);
- GstSegment *segment = &srcpad->segment;
-
- GST_OBJECT_LOCK (self);
- if (segment->position == -1 || segment->position < segment->start)
- next_time = segment->start;
- else
- next_time = segment->position;
-
- if (segment->stop != -1 && next_time > segment->stop)
- next_time = segment->stop;
-
- next_time = gst_segment_to_running_time (segment, GST_FORMAT_TIME, next_time);
- GST_OBJECT_UNLOCK (self);
-
- return next_time;
-}
-
-/**
- * gst_aggregator_update_segment:
- *
- * Subclasses should use this to update the segment on their
- * source pad, instead of directly pushing new segment events
- * downstream.
- *
- * Subclasses MUST call this before gst_aggregator_selected_samples(),
- * if it is used at all.
- *
- * Since: 1.18
- */
-void
-gst_aggregator_update_segment (GstAggregator * self, const GstSegment * segment)
-{
- g_return_if_fail (GST_IS_AGGREGATOR (self));
- g_return_if_fail (segment != NULL);
-
- GST_INFO_OBJECT (self, "Updating srcpad segment: %" GST_SEGMENT_FORMAT,
- segment);
-
- GST_OBJECT_LOCK (self);
- GST_AGGREGATOR_PAD (self->srcpad)->segment = *segment;
- self->priv->send_segment = TRUE;
- /* we have a segment from the subclass now and really shouldn't override
- * anything in that segment anymore, like the segment.position */
- self->priv->first_buffer = FALSE;
- GST_OBJECT_UNLOCK (self);
-}
-
-/**
- * gst_aggregator_selected_samples:
- * @pts: The presentation timestamp of the next output buffer
- * @dts: The decoding timestamp of the next output buffer
- * @duration: The duration of the next output buffer
- * @info: (nullable): a #GstStructure containing additional information
- *
- * Subclasses should call this when they have prepared the
- * buffers they will aggregate for each of their sink pads, but
- * before using any of the properties of the pads that govern
- * *how* aggregation should be performed, for example z-index
- * for video aggregators.
- *
- * If gst_aggregator_update_segment() is used by the subclass,
- * it MUST be called before gst_aggregator_selected_samples().
- *
- * This function MUST only be called from the #GstAggregatorClass::aggregate()
- * function.
- *
- * Since: 1.18
- */
-void
-gst_aggregator_selected_samples (GstAggregator * self,
- GstClockTime pts, GstClockTime dts, GstClockTime duration,
- GstStructure * info)
-{
- g_return_if_fail (GST_IS_AGGREGATOR (self));
-
- if (self->priv->emit_signals) {
- g_signal_emit (self, gst_aggregator_signals[SIGNAL_SAMPLES_SELECTED], 0,
- &GST_AGGREGATOR_PAD (self->srcpad)->segment, pts, dts, duration, info);
- }
-
- self->priv->selected_samples_called_or_warned = TRUE;
-}
diff --git a/libs/gst/base/gstaggregator.h b/libs/gst/base/gstaggregator.h
deleted file mode 100644
index 86fc70ff6d..0000000000
--- a/libs/gst/base/gstaggregator.h
+++ /dev/null
@@ -1,452 +0,0 @@
-/* GStreamer aggregator base class
- * Copyright (C) 2014 Mathieu Duponchelle <mathieu.duponchelle@oencreed.com>
- * Copyright (C) 2014 Thibault Saunier <tsaunier@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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_AGGREGATOR_H__
-#define __GST_AGGREGATOR_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-/**************************
- * GstAggregator Structs *
- *************************/
-
-typedef struct _GstAggregator GstAggregator;
-typedef struct _GstAggregatorPrivate GstAggregatorPrivate;
-typedef struct _GstAggregatorClass GstAggregatorClass;
-
-/************************
- * GstAggregatorPad API *
- ***********************/
-
-#define GST_TYPE_AGGREGATOR_PAD (gst_aggregator_pad_get_type())
-#define GST_AGGREGATOR_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPad))
-#define GST_AGGREGATOR_PAD_CAST(obj) ((GstAggregatorPad *)(obj))
-#define GST_AGGREGATOR_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPadClass))
-#define GST_AGGREGATOR_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPadClass))
-#define GST_IS_AGGREGATOR_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGGREGATOR_PAD))
-#define GST_IS_AGGREGATOR_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR_PAD))
-
-/****************************
- * GstAggregatorPad Structs *
- ***************************/
-
-typedef struct _GstAggregatorPad GstAggregatorPad;
-typedef struct _GstAggregatorPadClass GstAggregatorPadClass;
-typedef struct _GstAggregatorPadPrivate GstAggregatorPadPrivate;
-
-/**
- * GstAggregatorPad:
- * @segment: last segment received.
- *
- * The implementation the GstPad to use with #GstAggregator
- *
- * Since: 1.14
- */
-struct _GstAggregatorPad
-{
- GstPad parent;
-
- /*< public >*/
- /* Protected by the OBJECT_LOCK */
- GstSegment segment;
-
- /* < private > */
- GstAggregatorPadPrivate * priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstAggregatorPadClass:
- * @flush: Optional
- * Called when the pad has received a flush stop, this is the place
- * to flush any information specific to the pad, it allows for individual
- * pads to be flushed while others might not be.
- * @skip_buffer: Optional
- * Called before input buffers are queued in the pad, return %TRUE
- * if the buffer should be skipped.
- *
- * Since: 1.14
- */
-struct _GstAggregatorPadClass
-{
- GstPadClass parent_class;
-
- GstFlowReturn (*flush) (GstAggregatorPad * aggpad, GstAggregator * aggregator);
- gboolean (*skip_buffer) (GstAggregatorPad * aggpad, GstAggregator * aggregator, GstBuffer * buffer);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-GST_BASE_API
-GType gst_aggregator_pad_get_type (void);
-
-/****************************
- * GstAggregatorPad methods *
- ***************************/
-
-GST_BASE_API
-GstBuffer * gst_aggregator_pad_pop_buffer (GstAggregatorPad * pad);
-
-GST_BASE_API
-GstBuffer * gst_aggregator_pad_peek_buffer (GstAggregatorPad * pad);
-
-GST_BASE_API
-gboolean gst_aggregator_pad_drop_buffer (GstAggregatorPad * pad);
-
-GST_BASE_API
-gboolean gst_aggregator_pad_has_buffer (GstAggregatorPad * pad);
-
-GST_BASE_API
-gboolean gst_aggregator_pad_is_eos (GstAggregatorPad * pad);
-
-/*********************
- * GstAggregator API *
- ********************/
-
-#define GST_TYPE_AGGREGATOR (gst_aggregator_get_type())
-#define GST_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGGREGATOR,GstAggregator))
-#define GST_AGGREGATOR_CAST(obj) ((GstAggregator *)(obj))
-#define GST_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGGREGATOR,GstAggregatorClass))
-#define GST_AGGREGATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AGGREGATOR,GstAggregatorClass))
-#define GST_IS_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGGREGATOR))
-#define GST_IS_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR))
-
-#define GST_AGGREGATOR_FLOW_NEED_DATA GST_FLOW_CUSTOM_ERROR
-
-/**
- * GstAggregator:
- * @srcpad: the aggregator's source pad
- *
- * Aggregator base class object structure.
- *
- * Since: 1.14
- */
-struct _GstAggregator
-{
- GstElement parent;
-
- /*< public >*/
- GstPad * srcpad;
-
- /*< private >*/
- GstAggregatorPrivate * priv;
-
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-/**
- * GstAggregatorClass:
- * @flush: Optional.
- * Called after a successful flushing seek, once all the flush
- * stops have been received. Flush pad-specific data in
- * #GstAggregatorPad->flush.
- * @clip: Optional.
- * Called when a buffer is received on a sink pad, the task of
- * clipping it and translating it to the current segment falls
- * on the subclass. The function should use the segment of data
- * and the negotiated media type on the pad to perform
- * clipping of input buffer. This function takes ownership of
- * buf and should output a buffer or return NULL in
- * if the buffer should be dropped.
- * @finish_buffer: Optional.
- * Called when a subclass calls gst_aggregator_finish_buffer()
- * from their aggregate function to push out a buffer.
- * Subclasses can override this to modify or decorate buffers
- * before they get pushed out. This function takes ownership
- * of the buffer passed. Subclasses that override this method
- * should always chain up to the parent class virtual method.
- * @sink_event: Optional.
- * Called when an event is received on a sink pad, the subclass
- * should always chain up.
- * @sink_query: Optional.
- * Called when a query is received on a sink pad, the subclass
- * should always chain up.
- * @src_event: Optional.
- * Called when an event is received on the src pad, the subclass
- * should always chain up.
- * @src_query: Optional.
- * Called when a query is received on the src pad, the subclass
- * should always chain up.
- * @src_activate: Optional.
- * Called when the src pad is activated, it will start/stop its
- * pad task right after that call.
- * @aggregate: Mandatory.
- * Called when buffers are queued on all sinkpads. Classes
- * should iterate the GstElement->sinkpads and peek or steal
- * buffers from the #GstAggregatorPads. If the subclass returns
- * GST_FLOW_EOS, sending of the eos event will be taken care
- * of. Once / if a buffer has been constructed from the
- * aggregated buffers, the subclass should call _finish_buffer.
- * @stop: Optional.
- * Called when the element goes from PAUSED to READY.
- * The subclass should free all resources and reset its state.
- * @start: Optional.
- * Called when the element goes from READY to PAUSED.
- * The subclass should get ready to process
- * aggregated buffers.
- * @get_next_time: Optional.
- * Called when the element needs to know the running time of the next
- * rendered buffer for live pipelines. This causes deadline
- * based aggregation to occur. Defaults to returning
- * GST_CLOCK_TIME_NONE causing the element to wait for buffers
- * on all sink pads before aggregating.
- * @create_new_pad: Optional.
- * Called when a new pad needs to be created. Allows subclass that
- * don't have a single sink pad template to provide a pad based
- * on the provided information.
- * @update_src_caps: Lets subclasses update the #GstCaps representing
- * the src pad caps before usage. The result should end up
- * in @ret. Return %GST_AGGREGATOR_FLOW_NEED_DATA to indicate that the
- * element needs more information (caps, a buffer, etc) to
- * choose the correct caps. Should return ANY caps if the
- * stream has not caps at all.
- * @fixate_src_caps: Optional.
- * Fixate and return the src pad caps provided. The function takes
- * ownership of @caps and returns a fixated version of
- * @caps. @caps is not guaranteed to be writable.
- * @negotiated_src_caps: Optional.
- * Notifies subclasses what caps format has been negotiated
- * @decide_allocation: Optional.
- * Allows the subclass to influence the allocation choices.
- * Setup the allocation parameters for allocating output
- * buffers. The passed in query contains the result of the
- * downstream allocation query.
- * @propose_allocation: Optional.
- * Allows the subclass to handle the allocation query from upstream.
- * @negotiate: Optional.
- * Negotiate the caps with the peer (Since: 1.18).
- * @sink_event_pre_queue: Optional.
- * Called when an event is received on a sink pad before queueing up
- * serialized events. The subclass should always chain up (Since: 1.18).
- * @sink_query_pre_queue: Optional.
- * Called when a query is received on a sink pad before queueing up
- * serialized queries. The subclass should always chain up (Since: 1.18).
- *
- * The aggregator base class will handle in a thread-safe way all manners of
- * concurrent flushes, seeks, pad additions and removals, leaving to the
- * subclass the responsibility of clipping buffers, and aggregating buffers in
- * the way the implementor sees fit.
- *
- * It will also take care of event ordering (stream-start, segment, eos).
- *
- * Basically, a simple implementation will override @aggregate, and call
- * _finish_buffer from inside that function.
- *
- * Since: 1.14
- */
-struct _GstAggregatorClass {
- GstElementClass parent_class;
-
- GstFlowReturn (*flush) (GstAggregator * aggregator);
-
- GstBuffer * (*clip) (GstAggregator * aggregator,
- GstAggregatorPad * aggregator_pad,
- GstBuffer * buf);
-
- GstFlowReturn (*finish_buffer) (GstAggregator * aggregator,
- GstBuffer * buffer);
-
- /* sinkpads virtual methods */
- gboolean (*sink_event) (GstAggregator * aggregator,
- GstAggregatorPad * aggregator_pad,
- GstEvent * event);
-
- gboolean (*sink_query) (GstAggregator * aggregator,
- GstAggregatorPad * aggregator_pad,
- GstQuery * query);
-
- /* srcpad virtual methods */
- gboolean (*src_event) (GstAggregator * aggregator,
- GstEvent * event);
-
- gboolean (*src_query) (GstAggregator * aggregator,
- GstQuery * query);
-
- gboolean (*src_activate) (GstAggregator * aggregator,
- GstPadMode mode,
- gboolean active);
-
- GstFlowReturn (*aggregate) (GstAggregator * aggregator,
- gboolean timeout);
-
- gboolean (*stop) (GstAggregator * aggregator);
-
- gboolean (*start) (GstAggregator * aggregator);
-
- GstClockTime (*get_next_time) (GstAggregator * aggregator);
-
- GstAggregatorPad * (*create_new_pad) (GstAggregator * self,
- GstPadTemplate * templ,
- const gchar * req_name,
- const GstCaps * caps);
-
- /**
- * GstAggregatorClass::update_src_caps:
- * @ret: (out) (allow-none):
- */
- GstFlowReturn (*update_src_caps) (GstAggregator * self,
- GstCaps * caps,
- GstCaps ** ret);
- GstCaps * (*fixate_src_caps) (GstAggregator * self,
- GstCaps * caps);
- gboolean (*negotiated_src_caps) (GstAggregator * self,
- GstCaps * caps);
- gboolean (*decide_allocation) (GstAggregator * self,
- GstQuery * query);
- gboolean (*propose_allocation) (GstAggregator * self,
- GstAggregatorPad * pad,
- GstQuery * decide_query,
- GstQuery * query);
-
- gboolean (*negotiate) (GstAggregator * self);
-
- GstFlowReturn (*sink_event_pre_queue) (GstAggregator * aggregator,
- GstAggregatorPad * aggregator_pad,
- GstEvent * event);
-
- gboolean (*sink_query_pre_queue) (GstAggregator * aggregator,
- GstAggregatorPad * aggregator_pad,
- GstQuery * query);
-
- /**
- * GstAggregatorClass::finish_buffer_list:
- *
- * Optional. Equivalent of #GstAggregatorClass::finish_buffer for
- * buffer lists.
- *
- * Since: 1.18
- */
- GstFlowReturn (*finish_buffer_list) (GstAggregator * aggregator,
- GstBufferList * bufferlist);
- /**
- * GstAggregatorClass::peek_next_sample:
- *
- * See gst_aggregator_peek_next_sample().
- *
- * Since: 1.18
- */
- GstSample * (*peek_next_sample) (GstAggregator *aggregator,
- GstAggregatorPad * aggregator_pad);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE-5];
-};
-
-/************************************
- * GstAggregator convenience macros *
- ***********************************/
-
-/**
- * GST_AGGREGATOR_SRC_PAD:
- * @agg: a #GstAggregator
- *
- * Convenience macro to access the source pad of #GstAggregator
- *
- * Since: 1.6
- */
-#define GST_AGGREGATOR_SRC_PAD(agg) (((GstAggregator *)(agg))->srcpad)
-
-/*************************
- * GstAggregator methods *
- ************************/
-
-GST_BASE_API
-GstFlowReturn gst_aggregator_finish_buffer (GstAggregator * aggregator,
- GstBuffer * buffer);
-
-GST_BASE_API
-GstFlowReturn gst_aggregator_finish_buffer_list (GstAggregator * aggregator,
- GstBufferList * bufferlist);
-
-GST_BASE_API
-void gst_aggregator_set_src_caps (GstAggregator * self,
- GstCaps * caps);
-
-GST_BASE_API
-gboolean gst_aggregator_negotiate (GstAggregator * self);
-
-GST_BASE_API
-void gst_aggregator_set_latency (GstAggregator * self,
- GstClockTime min_latency,
- GstClockTime max_latency);
-
-GST_BASE_API
-GType gst_aggregator_get_type(void);
-
-GST_BASE_API
-GstClockTime gst_aggregator_get_latency (GstAggregator * self);
-
-GST_BASE_API
-GstBufferPool * gst_aggregator_get_buffer_pool (GstAggregator * self);
-
-GST_BASE_API
-void gst_aggregator_get_allocator (GstAggregator * self,
- GstAllocator ** allocator,
- GstAllocationParams * params);
-
-GST_BASE_API
-GstClockTime gst_aggregator_simple_get_next_time (GstAggregator * self);
-
-GST_BASE_API
-void gst_aggregator_update_segment (GstAggregator * self,
- const GstSegment * segment);
-
-GST_BASE_API
-GstSample * gst_aggregator_peek_next_sample (GstAggregator *self,
- GstAggregatorPad * pad);
-
-GST_BASE_API
-void gst_aggregator_selected_samples (GstAggregator * self,
- GstClockTime pts,
- GstClockTime dts,
- GstClockTime duration,
- GstStructure * info);
-
-/**
- * GstAggregatorStartTimeSelection:
- * @GST_AGGREGATOR_START_TIME_SELECTION_ZERO: Start at running time 0.
- * @GST_AGGREGATOR_START_TIME_SELECTION_FIRST: Start at the running time of
- * the first buffer that is received.
- * @GST_AGGREGATOR_START_TIME_SELECTION_SET: Start at the running time
- * selected by the `start-time` property.
- *
- * Since: 1.18
- */
-typedef enum
-{
- GST_AGGREGATOR_START_TIME_SELECTION_ZERO,
- GST_AGGREGATOR_START_TIME_SELECTION_FIRST,
- GST_AGGREGATOR_START_TIME_SELECTION_SET
-} GstAggregatorStartTimeSelection;
-
-GST_BASE_API
-GType gst_aggregator_start_time_selection_get_type (void);
-
-G_END_DECLS
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAggregator, gst_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAggregatorPad, gst_object_unref)
-
-#endif /* __GST_AGGREGATOR_H__ */
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
deleted file mode 100644
index b08a284906..0000000000
--- a/libs/gst/base/gstbaseparse.c
+++ /dev/null
@@ -1,5039 +0,0 @@
-/* GStreamer
- * Copyright (C) 2008 Nokia Corporation. All rights reserved.
- * Contact: Stefan Kost <stefan.kost@nokia.com>
- * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
- * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstbaseparse
- * @title: GstBaseParse
- * @short_description: Base class for stream parsers
- * @see_also: #GstBaseTransform
- *
- * This base class is for parser elements that process data and splits it
- * into separate audio/video/whatever frames.
- *
- * It provides for:
- *
- * * provides one sink pad and one source pad
- * * handles state changes
- * * can operate in pull mode or push mode
- * * handles seeking in both modes
- * * handles events (SEGMENT/EOS/FLUSH)
- * * handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT)
- * * handles flushing
- *
- * The purpose of this base class is to provide the basic functionality of
- * a parser and share a lot of rather complex code.
- *
- * # Description of the parsing mechanism:
- *
- * ## Set-up phase
- *
- * * #GstBaseParse calls #GstBaseParseClass::start to inform subclass
- * that data processing is about to start now.
- *
- * * #GstBaseParse class calls #GstBaseParseClass::set_sink_caps to
- * inform the subclass about incoming sinkpad caps. Subclass could
- * already set the srcpad caps accordingly, but this might be delayed
- * until calling gst_base_parse_finish_frame() with a non-queued frame.
- *
- * * At least at this point subclass needs to tell the #GstBaseParse class
- * how big data chunks it wants to receive (minimum frame size ). It can
- * do this with gst_base_parse_set_min_frame_size().
- *
- * * #GstBaseParse class sets up appropriate data passing mode (pull/push)
- * and starts to process the data.
- *
- * ## Parsing phase
- *
- * * #GstBaseParse gathers at least min_frame_size bytes of data either
- * by pulling it from upstream or collecting buffers in an internal
- * #GstAdapter.
- *
- * * A buffer of (at least) min_frame_size bytes is passed to subclass
- * with #GstBaseParseClass::handle_frame. Subclass checks the contents
- * and can optionally return #GST_FLOW_OK along with an amount of data
- * to be skipped to find a valid frame (which will result in a
- * subsequent DISCONT). If, otherwise, the buffer does not hold a
- * complete frame, #GstBaseParseClass::handle_frame can merely return
- * and will be called again when additional data is available. In push
- * mode this amounts to an additional input buffer (thus minimal
- * additional latency), in pull mode this amounts to some arbitrary
- * reasonable buffer size increase.
- *
- * Of course, gst_base_parse_set_min_frame_size() could also be used if
- * a very specific known amount of additional data is required. If,
- * however, the buffer holds a complete valid frame, it can pass the
- * size of this frame to gst_base_parse_finish_frame().
- *
- * If acting as a converter, it can also merely indicate consumed input
- * data while simultaneously providing custom output data. Note that
- * baseclass performs some processing (such as tracking overall consumed
- * data rate versus duration) for each finished frame, but other state
- * is only updated upon each call to #GstBaseParseClass::handle_frame
- * (such as tracking upstream input timestamp).
- *
- * Subclass is also responsible for setting the buffer metadata
- * (e.g. buffer timestamp and duration, or keyframe if applicable).
- * (although the latter can also be done by #GstBaseParse if it is
- * appropriately configured, see below). Frame is provided with
- * timestamp derived from upstream (as much as generally possible),
- * duration obtained from configuration (see below), and offset
- * if meaningful (in pull mode).
- *
- * Note that #GstBaseParseClass::handle_frame might receive any small
- * amount of input data when leftover data is being drained (e.g. at
- * EOS).
- *
- * * As part of finish frame processing, just prior to actually pushing
- * the buffer in question, it is passed to
- * #GstBaseParseClass::pre_push_frame which gives subclass yet one last
- * chance to examine buffer metadata, or to send some custom (tag)
- * events, or to perform custom (segment) filtering.
- *
- * * During the parsing process #GstBaseParseClass will handle both srcpad
- * and sinkpad events. They will be passed to subclass if
- * #GstBaseParseClass::sink_event or #GstBaseParseClass::src_event
- * implementations have been provided.
- *
- * ## Shutdown phase
- *
- * * #GstBaseParse class calls #GstBaseParseClass::stop to inform the
- * subclass that data parsing will be stopped.
- *
- * Subclass is responsible for providing pad template caps for source and
- * sink pads. The pads need to be named "sink" and "src". It also needs to
- * set the fixed caps on srcpad, when the format is ensured (e.g. when
- * base class calls subclass' #GstBaseParseClass::set_sink_caps function).
- *
- * This base class uses %GST_FORMAT_DEFAULT as a meaning of frames. So,
- * subclass conversion routine needs to know that conversion from
- * %GST_FORMAT_TIME to %GST_FORMAT_DEFAULT must return the
- * frame number that can be found from the given byte position.
- *
- * #GstBaseParse uses subclasses conversion methods also for seeking (or
- * otherwise uses its own default one, see also below).
- *
- * Subclass @start and @stop functions will be called to inform the beginning
- * and end of data processing.
- *
- * Things that subclass need to take care of:
- *
- * * Provide pad templates
- * * Fixate the source pad caps when appropriate
- * * Inform base class how big data chunks should be retrieved. This is
- * done with gst_base_parse_set_min_frame_size() function.
- * * Examine data chunks passed to subclass with
- * #GstBaseParseClass::handle_frame and pass proper frame(s) to
- * gst_base_parse_finish_frame(), and setting src pad caps and timestamps
- * on frame.
- * * Provide conversion functions
- * * Update the duration information with gst_base_parse_set_duration()
- * * Optionally passthrough using gst_base_parse_set_passthrough()
- * * Configure various baseparse parameters using
- * gst_base_parse_set_average_bitrate(), gst_base_parse_set_syncable()
- * and gst_base_parse_set_frame_rate().
- *
- * * In particular, if subclass is unable to determine a duration, but
- * parsing (or specs) yields a frames per seconds rate, then this can be
- * provided to #GstBaseParse to enable it to cater for buffer time
- * metadata (which will be taken from upstream as much as
- * possible). Internally keeping track of frame durations and respective
- * sizes that have been pushed provides #GstBaseParse with an estimated
- * bitrate. A default #GstBaseParseClass::convert (used if not
- * overridden) will then use these rates to perform obvious conversions.
- * These rates are also used to update (estimated) duration at regular
- * frame intervals.
- *
- */
-
-/* TODO:
- * - In push mode provide a queue of adapter-"queued" buffers for upstream
- * buffer metadata
- * - Queue buffers/events until caps are set
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <gst/base/gstadapter.h>
-
-#include "gstbaseparse.h"
-
-/* FIXME: get rid of old GstIndex code */
-#include "gstindex.h"
-#include "gstindex.c"
-#include "gstmemindex.c"
-
-#define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC (1 << 0)
-
-#define MIN_FRAMES_TO_POST_BITRATE 10
-#define TARGET_DIFFERENCE (20 * GST_SECOND)
-#define MAX_INDEX_ENTRIES 4096
-#define UPDATE_THRESHOLD 2
-
-#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
-
-GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
-#define GST_CAT_DEFAULT gst_base_parse_debug
-
-/* Supported formats */
-static const GstFormat fmtlist[] = {
- GST_FORMAT_DEFAULT,
- GST_FORMAT_BYTES,
- GST_FORMAT_TIME,
- GST_FORMAT_UNDEFINED
-};
-
-struct _GstBaseParsePrivate
-{
- GstPadMode pad_mode;
-
- GstAdapter *adapter;
-
- gint64 duration;
- GstFormat duration_fmt;
- gint64 estimated_duration;
- gint64 estimated_drift;
-
- guint min_frame_size;
- gboolean disable_passthrough;
- gboolean passthrough;
- gboolean pts_interpolate;
- gboolean infer_ts;
- gboolean syncable;
- gboolean has_timing_info;
- guint fps_num, fps_den;
- gint update_interval;
- guint bitrate;
- guint lead_in, lead_out;
- GstClockTime lead_in_ts, lead_out_ts;
- GstClockTime min_latency, max_latency;
-
- gboolean discont;
- gboolean flushing;
- gboolean drain;
- gboolean saw_gaps;
-
- gint64 offset;
- gint64 sync_offset;
- GstClockTime next_pts;
- GstClockTime next_dts;
- GstClockTime prev_pts;
- GstClockTime prev_dts;
- gboolean prev_dts_from_pts;
- GstClockTime frame_duration;
- gboolean seen_keyframe;
- gboolean is_video;
- gint flushed;
-
- guint64 framecount;
- guint64 bytecount;
- guint64 data_bytecount;
- guint64 acc_duration;
- GstClockTime first_frame_pts;
- GstClockTime first_frame_dts;
- gint64 first_frame_offset;
-
- gboolean post_min_bitrate;
- gboolean post_avg_bitrate;
- gboolean post_max_bitrate;
-
- guint min_bitrate;
- guint avg_bitrate;
- guint max_bitrate;
- guint posted_avg_bitrate;
-
- /* frames/buffers that are queued and ready to go on OK */
- GQueue queued_frames;
-
- GstBuffer *cache;
-
- /* index entry storage, either ours or provided */
- GstIndex *index;
- gint index_id;
- gboolean own_index;
- GMutex index_lock;
-
- /* seek table entries only maintained if upstream is BYTE seekable */
- gboolean upstream_seekable;
- gboolean upstream_has_duration;
- gint64 upstream_size;
- GstFormat upstream_format;
- /* minimum distance between two index entries */
- GstClockTimeDiff idx_interval;
- guint64 idx_byte_interval;
- /* ts and offset of last entry added */
- GstClockTime index_last_ts;
- gint64 index_last_offset;
- gboolean index_last_valid;
-
- /* timestamps currently produced are accurate, e.g. started from 0 onwards */
- gboolean exact_position;
- /* seek events are temporarily kept to match them with newsegments */
- GSList *pending_seeks;
-
- /* reverse playback */
- GSList *buffers_pending;
- GSList *buffers_head;
- GSList *buffers_queued;
- GSList *buffers_send;
- GstClockTime last_pts;
- GstClockTime last_dts;
- gint64 last_offset;
-
- /* Pending serialized events */
- GList *pending_events;
-
- /* If baseparse has checked the caps to identify if it is
- * handling video or audio */
- gboolean checked_media;
-
- /* offset of last parsed frame/data */
- gint64 prev_offset;
- /* force a new frame, regardless of offset */
- gboolean new_frame;
- /* whether we are merely scanning for a frame */
- gboolean scanning;
- /* ... and resulting frame, if any */
- GstBaseParseFrame *scanned_frame;
-
- /* TRUE if we're still detecting the format, i.e.
- * if ::detect() is still called for future buffers */
- gboolean detecting;
- GList *detect_buffers;
- guint detect_buffers_size;
-
- /* True when no buffers have been received yet */
- gboolean first_buffer;
-
- /* if TRUE, a STREAM_START event needs to be pushed */
- gboolean push_stream_start;
-
- /* When we need to skip more data than we have currently */
- guint skip;
-
- /* Tag handling (stream tags only, global tags are passed through as-is) */
- GstTagList *upstream_tags;
- GstTagList *parser_tags;
- GstTagMergeMode parser_tags_merge_mode;
- gboolean tags_changed;
-
- /* Current segment seqnum */
- guint32 segment_seqnum;
-};
-
-typedef struct _GstBaseParseSeek
-{
- GstSegment segment;
- gboolean accurate;
- gint64 offset;
- GstClockTime start_ts;
-} GstBaseParseSeek;
-
-#define DEFAULT_DISABLE_PASSTHROUGH FALSE
-
-enum
-{
- PROP_0,
- PROP_DISABLE_PASSTHROUGH,
- PROP_LAST
-};
-
-#define GST_BASE_PARSE_INDEX_LOCK(parse) \
- g_mutex_lock (&parse->priv->index_lock);
-#define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
- g_mutex_unlock (&parse->priv->index_lock);
-
-static GstElementClass *parent_class = NULL;
-static gint base_parse_private_offset = 0;
-
-static void gst_base_parse_class_init (GstBaseParseClass * klass);
-static void gst_base_parse_init (GstBaseParse * parse,
- GstBaseParseClass * klass);
-
-GType
-gst_base_parse_get_type (void)
-{
- static gsize base_parse_type = 0;
-
- if (g_once_init_enter (&base_parse_type)) {
- static const GTypeInfo base_parse_info = {
- sizeof (GstBaseParseClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gst_base_parse_class_init,
- NULL,
- NULL,
- sizeof (GstBaseParse),
- 0,
- (GInstanceInitFunc) gst_base_parse_init,
- };
- GType _type;
-
- _type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstBaseParse", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
-
- base_parse_private_offset =
- g_type_add_instance_private (_type, sizeof (GstBaseParsePrivate));
-
- g_once_init_leave (&base_parse_type, _type);
- }
- return (GType) base_parse_type;
-}
-
-static inline GstBaseParsePrivate *
-gst_base_parse_get_instance_private (GstBaseParse * self)
-{
- return (G_STRUCT_MEMBER_P (self, base_parse_private_offset));
-}
-
-static void gst_base_parse_finalize (GObject * object);
-
-static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
- GstStateChange transition);
-static void gst_base_parse_reset (GstBaseParse * parse);
-
-#if 0
-static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
-static GstIndex *gst_base_parse_get_index (GstElement * element);
-#endif
-
-static gboolean gst_base_parse_sink_activate (GstPad * sinkpad,
- GstObject * parent);
-static gboolean gst_base_parse_sink_activate_mode (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active);
-static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
- GstEvent * event);
-static void gst_base_parse_set_upstream_tags (GstBaseParse * parse,
- GstTagList * taglist);
-
-static void gst_base_parse_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_base_parse_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-
-static gboolean gst_base_parse_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_base_parse_sink_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-
-static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent,
- GstBuffer * buffer);
-static void gst_base_parse_loop (GstPad * pad);
-
-static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame);
-
-static gboolean gst_base_parse_sink_event_default (GstBaseParse * parse,
- GstEvent * event);
-
-static gboolean gst_base_parse_src_event_default (GstBaseParse * parse,
- GstEvent * event);
-
-static gboolean gst_base_parse_sink_query_default (GstBaseParse * parse,
- GstQuery * query);
-static gboolean gst_base_parse_src_query_default (GstBaseParse * parse,
- GstQuery * query);
-
-static gint64 gst_base_parse_find_offset (GstBaseParse * parse,
- GstClockTime time, gboolean before, GstClockTime * _ts);
-static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse,
- GstClockTime * _time, gint64 * _offset);
-
-static GstFlowReturn gst_base_parse_start_fragment (GstBaseParse * parse);
-static GstFlowReturn gst_base_parse_finish_fragment (GstBaseParse * parse,
- gboolean prev_head);
-static GstFlowReturn gst_base_parse_send_buffers (GstBaseParse * parse);
-
-static inline GstFlowReturn gst_base_parse_check_sync (GstBaseParse * parse);
-
-static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
-
-static void gst_base_parse_push_pending_events (GstBaseParse * parse);
-
-static void
-gst_base_parse_clear_queues (GstBaseParse * parse)
-{
- g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL);
- g_slist_free (parse->priv->buffers_queued);
- parse->priv->buffers_queued = NULL;
- g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref,
- NULL);
- g_slist_free (parse->priv->buffers_pending);
- parse->priv->buffers_pending = NULL;
- g_slist_foreach (parse->priv->buffers_head, (GFunc) gst_buffer_unref, NULL);
- g_slist_free (parse->priv->buffers_head);
- parse->priv->buffers_head = NULL;
- g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL);
- g_slist_free (parse->priv->buffers_send);
- parse->priv->buffers_send = NULL;
-
- g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
- g_list_free (parse->priv->detect_buffers);
- parse->priv->detect_buffers = NULL;
- parse->priv->detect_buffers_size = 0;
-
- g_queue_foreach (&parse->priv->queued_frames,
- (GFunc) gst_base_parse_frame_free, NULL);
- g_queue_clear (&parse->priv->queued_frames);
-
- gst_buffer_replace (&parse->priv->cache, NULL);
-
- g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL);
- g_list_free (parse->priv->pending_events);
- parse->priv->pending_events = NULL;
-
- parse->priv->checked_media = FALSE;
-}
-
-static void
-gst_base_parse_finalize (GObject * object)
-{
- GstBaseParse *parse = GST_BASE_PARSE (object);
-
- g_object_unref (parse->priv->adapter);
-
- if (parse->priv->index) {
- gst_object_unref (parse->priv->index);
- parse->priv->index = NULL;
- }
- g_mutex_clear (&parse->priv->index_lock);
-
- gst_base_parse_clear_queues (parse);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_base_parse_class_init (GstBaseParseClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- if (base_parse_private_offset != 0)
- g_type_class_adjust_private_offset (klass, &base_parse_private_offset);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_parse_set_property);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_parse_get_property);
-
- /**
- * GstBaseParse:disable-passthrough:
- *
- * If set to %TRUE, baseparse will unconditionally force parsing of the
- * incoming data. This can be required in the rare cases where the incoming
- * side-data (caps, pts, dts, ...) is not trusted by the user and wants to
- * force validation and parsing of the incoming data.
- * If set to %FALSE, decision of whether to parse the data or not is up to
- * the implementation (standard behaviour).
- */
- g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH,
- g_param_spec_boolean ("disable-passthrough", "Disable passthrough",
- "Force processing (disables passthrough)",
- DEFAULT_DISABLE_PASSTHROUGH,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gstelement_class = (GstElementClass *) klass;
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
-
-#if 0
- gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
- gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
-#endif
-
- /* Default handlers */
- klass->sink_event = gst_base_parse_sink_event_default;
- klass->src_event = gst_base_parse_src_event_default;
- klass->sink_query = gst_base_parse_sink_query_default;
- klass->src_query = gst_base_parse_src_query_default;
- klass->convert = gst_base_parse_convert_default;
-
- GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
- "baseparse element");
-}
-
-static void
-gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
-{
- GstPadTemplate *pad_template;
-
- GST_DEBUG_OBJECT (parse, "gst_base_parse_init");
-
- parse->priv = gst_base_parse_get_instance_private (parse);
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
- g_return_if_fail (pad_template != NULL);
- parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
- gst_pad_set_event_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
- gst_pad_set_query_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_sink_query));
- gst_pad_set_chain_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_chain));
- gst_pad_set_activate_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
- gst_pad_set_activatemode_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode));
- GST_PAD_SET_PROXY_ALLOCATION (parse->sinkpad);
- gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
-
- GST_DEBUG_OBJECT (parse, "sinkpad created");
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
- g_return_if_fail (pad_template != NULL);
- parse->srcpad = gst_pad_new_from_template (pad_template, "src");
- gst_pad_set_event_function (parse->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
- gst_pad_set_query_function (parse->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_parse_src_query));
- gst_pad_use_fixed_caps (parse->srcpad);
- gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
- GST_DEBUG_OBJECT (parse, "src created");
-
- g_queue_init (&parse->priv->queued_frames);
-
- parse->priv->adapter = gst_adapter_new ();
-
- parse->priv->pad_mode = GST_PAD_MODE_NONE;
-
- g_mutex_init (&parse->priv->index_lock);
-
- /* init state */
- gst_base_parse_reset (parse);
- GST_DEBUG_OBJECT (parse, "init ok");
-
- GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
-
- parse->priv->upstream_tags = NULL;
- parse->priv->parser_tags = NULL;
- parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND;
- parse->priv->disable_passthrough = DEFAULT_DISABLE_PASSTHROUGH;
-}
-
-static void
-gst_base_parse_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstBaseParse *parse = GST_BASE_PARSE (object);
-
- switch (prop_id) {
- case PROP_DISABLE_PASSTHROUGH:
- parse->priv->disable_passthrough = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstBaseParse *parse = GST_BASE_PARSE (object);
-
- switch (prop_id) {
- case PROP_DISABLE_PASSTHROUGH:
- g_value_set_boolean (value, parse->priv->disable_passthrough);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/**
- * gst_base_parse_frame_copy:
- * @frame: a #GstBaseParseFrame
- *
- * Copies a #GstBaseParseFrame.
- *
- * Returns: A copy of @frame
- *
- * Since: 1.12.1
- */
-GstBaseParseFrame *
-gst_base_parse_frame_copy (GstBaseParseFrame * frame)
-{
- GstBaseParseFrame *copy;
-
- copy = g_slice_dup (GstBaseParseFrame, frame);
- copy->buffer = gst_buffer_ref (frame->buffer);
- copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
-
- GST_TRACE ("copied frame %p -> %p", frame, copy);
-
- return copy;
-}
-
-/**
- * gst_base_parse_frame_free:
- * @frame: A #GstBaseParseFrame
- *
- * Frees the provided @frame.
- */
-void
-gst_base_parse_frame_free (GstBaseParseFrame * frame)
-{
- GST_TRACE ("freeing frame %p", frame);
-
- if (frame->buffer) {
- gst_buffer_unref (frame->buffer);
- frame->buffer = NULL;
- }
-
- if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
- g_slice_free (GstBaseParseFrame, frame);
- } else {
- memset (frame, 0, sizeof (*frame));
- }
-}
-
-G_DEFINE_BOXED_TYPE (GstBaseParseFrame, gst_base_parse_frame,
- (GBoxedCopyFunc) gst_base_parse_frame_copy,
- (GBoxedFreeFunc) gst_base_parse_frame_free);
-
-/**
- * gst_base_parse_frame_init:
- * @frame: #GstBaseParseFrame.
- *
- * Sets a #GstBaseParseFrame to initial state. Currently this means
- * all public fields are zero-ed and a private flag is set to make
- * sure gst_base_parse_frame_free() only frees the contents but not
- * the actual frame. Use this function to initialise a #GstBaseParseFrame
- * allocated on the stack.
- */
-void
-gst_base_parse_frame_init (GstBaseParseFrame * frame)
-{
- memset (frame, 0, sizeof (GstBaseParseFrame));
- frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
- GST_TRACE ("inited frame %p", frame);
-}
-
-/**
- * gst_base_parse_frame_new:
- * @buffer: (transfer none): a #GstBuffer
- * @flags: the flags
- * @overhead: number of bytes in this frame which should be counted as
- * metadata overhead, ie. not used to calculate the average bitrate.
- * Set to -1 to mark the entire frame as metadata. If in doubt, set to 0.
- *
- * Allocates a new #GstBaseParseFrame. This function is mainly for bindings,
- * elements written in C should usually allocate the frame on the stack and
- * then use gst_base_parse_frame_init() to initialise it.
- *
- * Returns: a newly-allocated #GstBaseParseFrame. Free with
- * gst_base_parse_frame_free() when no longer needed.
- */
-GstBaseParseFrame *
-gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags,
- gint overhead)
-{
- GstBaseParseFrame *frame;
-
- frame = g_slice_new0 (GstBaseParseFrame);
- frame->buffer = gst_buffer_ref (buffer);
-
- GST_TRACE ("created frame %p", frame);
- return frame;
-}
-
-static inline void
-gst_base_parse_update_flags (GstBaseParse * parse)
-{
- parse->flags = 0;
-
- /* set flags one by one for clarity */
- if (G_UNLIKELY (parse->priv->drain))
- parse->flags |= GST_BASE_PARSE_FLAG_DRAINING;
-
- /* losing sync is pretty much a discont (and vice versa), no ? */
- if (G_UNLIKELY (parse->priv->discont))
- parse->flags |= GST_BASE_PARSE_FLAG_LOST_SYNC;
-}
-
-static inline void
-gst_base_parse_update_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- if (G_UNLIKELY (parse->priv->discont)) {
- GST_DEBUG_OBJECT (parse, "marking DISCONT");
- GST_BUFFER_FLAG_SET (frame->buffer, GST_BUFFER_FLAG_DISCONT);
- } else {
- GST_BUFFER_FLAG_UNSET (frame->buffer, GST_BUFFER_FLAG_DISCONT);
- }
-
- if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) {
- GST_LOG_OBJECT (parse, "marking as new frame");
- frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME;
- }
-
- frame->offset = parse->priv->prev_offset = parse->priv->offset;
-}
-
-static void
-gst_base_parse_reset (GstBaseParse * parse)
-{
- GST_OBJECT_LOCK (parse);
- gst_segment_init (&parse->segment, GST_FORMAT_TIME);
- parse->priv->duration = -1;
- parse->priv->min_frame_size = 1;
- parse->priv->discont = TRUE;
- parse->priv->flushing = FALSE;
- parse->priv->saw_gaps = FALSE;
- parse->priv->offset = 0;
- parse->priv->sync_offset = 0;
- parse->priv->update_interval = -1;
- parse->priv->fps_num = parse->priv->fps_den = 0;
- parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
- parse->priv->lead_in = parse->priv->lead_out = 0;
- parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
- parse->priv->bitrate = 0;
- parse->priv->framecount = 0;
- parse->priv->bytecount = 0;
- parse->priv->acc_duration = 0;
- parse->priv->first_frame_pts = GST_CLOCK_TIME_NONE;
- parse->priv->first_frame_dts = GST_CLOCK_TIME_NONE;
- parse->priv->first_frame_offset = -1;
- parse->priv->estimated_duration = -1;
- parse->priv->estimated_drift = 0;
- parse->priv->next_pts = GST_CLOCK_TIME_NONE;
- parse->priv->next_dts = 0;
- parse->priv->syncable = TRUE;
- parse->priv->passthrough = FALSE;
- parse->priv->pts_interpolate = TRUE;
- parse->priv->infer_ts = TRUE;
- parse->priv->has_timing_info = FALSE;
- parse->priv->min_bitrate = G_MAXUINT;
- parse->priv->max_bitrate = 0;
- parse->priv->avg_bitrate = 0;
- parse->priv->posted_avg_bitrate = 0;
-
- parse->priv->index_last_ts = GST_CLOCK_TIME_NONE;
- parse->priv->index_last_offset = -1;
- parse->priv->index_last_valid = TRUE;
- parse->priv->upstream_seekable = FALSE;
- parse->priv->upstream_size = 0;
- parse->priv->upstream_has_duration = FALSE;
- parse->priv->upstream_format = GST_FORMAT_UNDEFINED;
- parse->priv->idx_interval = 0;
- parse->priv->idx_byte_interval = 0;
- parse->priv->exact_position = TRUE;
- parse->priv->seen_keyframe = FALSE;
- parse->priv->checked_media = FALSE;
-
- parse->priv->last_dts = GST_CLOCK_TIME_NONE;
- parse->priv->last_pts = GST_CLOCK_TIME_NONE;
- parse->priv->last_offset = 0;
-
- parse->priv->skip = 0;
-
- g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
- NULL);
- g_list_free (parse->priv->pending_events);
- parse->priv->pending_events = NULL;
-
- if (parse->priv->cache) {
- gst_buffer_unref (parse->priv->cache);
- parse->priv->cache = NULL;
- }
-
- g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
- g_slist_free (parse->priv->pending_seeks);
- parse->priv->pending_seeks = NULL;
-
- if (parse->priv->adapter)
- gst_adapter_clear (parse->priv->adapter);
-
- gst_base_parse_set_upstream_tags (parse, NULL);
-
- if (parse->priv->parser_tags) {
- gst_tag_list_unref (parse->priv->parser_tags);
- parse->priv->parser_tags = NULL;
- }
- parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND;
-
- parse->priv->new_frame = TRUE;
-
- parse->priv->first_buffer = TRUE;
-
- g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
- g_list_free (parse->priv->detect_buffers);
- parse->priv->detect_buffers = NULL;
- parse->priv->detect_buffers_size = 0;
-
- parse->priv->segment_seqnum = GST_SEQNUM_INVALID;
- GST_OBJECT_UNLOCK (parse);
-}
-
-static gboolean
-gst_base_parse_check_bitrate_tag (GstBaseParse * parse, const gchar * tag)
-{
- gboolean got_tag = FALSE;
- guint n = 0;
-
- if (parse->priv->upstream_tags != NULL)
- got_tag = gst_tag_list_get_uint (parse->priv->upstream_tags, tag, &n);
-
- if (!got_tag && parse->priv->parser_tags != NULL)
- got_tag = gst_tag_list_get_uint (parse->priv->parser_tags, tag, &n);
-
- return got_tag;
-}
-
-/* check if upstream or subclass tags contain bitrates already */
-static void
-gst_base_parse_check_bitrate_tags (GstBaseParse * parse)
-{
- parse->priv->post_min_bitrate =
- !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MINIMUM_BITRATE);
- parse->priv->post_avg_bitrate =
- !gst_base_parse_check_bitrate_tag (parse, GST_TAG_BITRATE);
- parse->priv->post_max_bitrate =
- !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MAXIMUM_BITRATE);
-}
-
-/* Queues new tag event with the current combined state of the stream tags
- * (i.e. upstream tags merged with subclass tags and current baseparse tags) */
-static void
-gst_base_parse_queue_tag_event_update (GstBaseParse * parse)
-{
- GstTagList *merged_tags;
-
- GST_LOG_OBJECT (parse, "upstream : %" GST_PTR_FORMAT,
- parse->priv->upstream_tags);
- GST_LOG_OBJECT (parse, "parser : %" GST_PTR_FORMAT,
- parse->priv->parser_tags);
- GST_LOG_OBJECT (parse, "mode : %d", parse->priv->parser_tags_merge_mode);
-
- merged_tags =
- gst_tag_list_merge (parse->priv->upstream_tags, parse->priv->parser_tags,
- parse->priv->parser_tags_merge_mode);
-
- GST_DEBUG_OBJECT (parse, "merged : %" GST_PTR_FORMAT, merged_tags);
-
- if (merged_tags == NULL)
- return;
-
- if (gst_tag_list_is_empty (merged_tags)) {
- gst_tag_list_unref (merged_tags);
- return;
- }
-
- if (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE) {
- /* only add bitrate tags to non-empty taglists for now, and only if neither
- * upstream tags nor the subclass sets the bitrate tag in question already */
- if (parse->priv->min_bitrate != G_MAXUINT && parse->priv->post_min_bitrate) {
- GST_LOG_OBJECT (parse, "adding min bitrate %u", parse->priv->min_bitrate);
- gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
- GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL);
- }
- if (parse->priv->max_bitrate != 0 && parse->priv->post_max_bitrate) {
- GST_LOG_OBJECT (parse, "adding max bitrate %u", parse->priv->max_bitrate);
- gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
- GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL);
- }
- if (parse->priv->avg_bitrate != 0 && parse->priv->post_avg_bitrate) {
- parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate;
- GST_LOG_OBJECT (parse, "adding avg bitrate %u", parse->priv->avg_bitrate);
- gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
- GST_TAG_BITRATE, parse->priv->avg_bitrate, NULL);
- }
- }
-
- parse->priv->pending_events =
- g_list_prepend (parse->priv->pending_events,
- gst_event_new_tag (merged_tags));
-}
-
-/* gst_base_parse_parse_frame:
- * @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
- *
- * Default callback for parse_frame.
- */
-static GstFlowReturn
-gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- GstBuffer *buffer = frame->buffer;
- gboolean must_approximate_pts = !GST_BUFFER_PTS_IS_VALID (buffer)
- && GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts);
- gboolean must_approximate_dts = !GST_BUFFER_DTS_IS_VALID (buffer)
- && GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts);
-
- if (must_approximate_pts) {
- GST_BUFFER_PTS (buffer) = parse->priv->next_pts;
- if (!must_approximate_dts
- && GST_BUFFER_DTS (buffer) > parse->priv->next_pts
- && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer))) {
- /* Can't present a frame before it's decoded: change the pts! This can
- * happen, for example, when accumulating rounding errors from the
- * buffer durations. Assume DTS is correct because only PTS is
- * approximated here */
- GST_LOG_OBJECT (parse,
- "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
- "), set PTS = DTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
- GST_BUFFER_PTS (buffer) = GST_BUFFER_DTS (buffer);
- }
- }
-
- if (must_approximate_dts) {
- if (!must_approximate_pts
- && GST_BUFFER_PTS (buffer) < parse->priv->next_dts) {
- /* Can't present a frame before it's decoded: change the dts! This can
- * happen, for example, when accumulating rounding errors from the
- * buffer durations. Assume PTS is correct because only DTS is
- * approximated here */
- GST_LOG_OBJECT (parse,
- "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
- "), set DTS = PTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
- GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
- } else {
- GST_BUFFER_DTS (buffer) = parse->priv->next_dts;
- }
- }
-
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer))
- && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer))
- && GST_BUFFER_PTS (buffer) < GST_BUFFER_DTS (buffer)) {
- /* Can't present a frame before it's decoded: change the pts! This can
- * happen, for example, when accumulating rounding errors from the buffer
- * durations. PTS and DTS are either both approximated or both from the
- * original buffer timestamp. Set PTS = DTS because the opposite has been
- * observed to cause DTS going backwards */
- GST_LOG_OBJECT (parse,
- "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
- "), set PTS = DTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
- GST_BUFFER_PTS (buffer) = GST_BUFFER_DTS (buffer);
- }
-
- if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
- GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
- GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
- }
- return GST_FLOW_OK;
-}
-
-/* gst_base_parse_convert:
- * @parse: #GstBaseParse.
- * @src_format: #GstFormat describing the source format.
- * @src_value: Source value to be converted.
- * @dest_format: #GstFormat defining the converted format.
- * @dest_value: Pointer where the conversion result will be put.
- *
- * Converts using configured "convert" vmethod in #GstBaseParse class.
- *
- * Returns: %TRUE if conversion was successful.
- */
-static gboolean
-gst_base_parse_convert (GstBaseParse * parse,
- GstFormat src_format,
- gint64 src_value, GstFormat dest_format, gint64 * dest_value)
-{
- GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
- gboolean ret;
-
- g_return_val_if_fail (dest_value != NULL, FALSE);
-
- if (!klass->convert)
- return FALSE;
-
- ret = klass->convert (parse, src_format, src_value, dest_format, dest_value);
-
-#ifndef GST_DISABLE_GST_DEBUG
- {
- if (ret) {
- if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
- GST_LOG_OBJECT (parse,
- "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT,
- GST_TIME_ARGS (src_value), *dest_value);
- } else if (dest_format == GST_FORMAT_TIME &&
- src_format == GST_FORMAT_BYTES) {
- GST_LOG_OBJECT (parse,
- "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT,
- src_value, GST_TIME_ARGS (*dest_value));
- } else {
- GST_LOG_OBJECT (parse,
- "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT,
- GST_STR_NULL (gst_format_get_name (src_format)),
- GST_STR_NULL (gst_format_get_name (dest_format)),
- src_value, *dest_value);
- }
- } else {
- GST_DEBUG_OBJECT (parse, "conversion failed");
- }
- }
-#endif
-
- return ret;
-}
-
-static gboolean
-update_upstream_provided (GQuark field_id, const GValue * value,
- gpointer user_data)
-{
- GstCaps *default_caps = user_data;
- gint i;
- gint caps_size;
-
- caps_size = gst_caps_get_size (default_caps);
- for (i = 0; i < caps_size; i++) {
- GstStructure *structure = gst_caps_get_structure (default_caps, i);
- if (!gst_structure_id_has_field (structure, field_id)) {
- gst_structure_id_set_value (structure, field_id, value);
- }
- /* XXX: maybe try to fixate better than gst_caps_fixate() the
- * downstream caps based on upstream values if possible */
- }
-
- return TRUE;
-}
-
-static GstCaps *
-gst_base_parse_negotiate_default_caps (GstBaseParse * parse)
-{
- GstCaps *caps, *templcaps;
- GstCaps *sinkcaps = NULL;
- GstCaps *default_caps = NULL;
- GstStructure *structure;
-
- templcaps = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse));
- caps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), templcaps);
- if (caps)
- gst_caps_unref (templcaps);
- else
- caps = templcaps;
- templcaps = NULL;
-
- if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
- goto caps_error;
- }
-
- GST_LOG_OBJECT (parse, "peer caps %" GST_PTR_FORMAT, caps);
-
- /* before fixating, try to use whatever upstream provided */
- default_caps = gst_caps_copy (caps);
- sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
-
- GST_LOG_OBJECT (parse, "current caps %" GST_PTR_FORMAT " for sinkpad",
- sinkcaps);
-
- if (sinkcaps) {
- structure = gst_caps_get_structure (sinkcaps, 0);
- gst_structure_foreach (structure, update_upstream_provided, default_caps);
- }
-
- default_caps = gst_caps_fixate (default_caps);
-
- if (!default_caps) {
- GST_WARNING_OBJECT (parse, "Failed to create default caps !");
- goto caps_error;
- }
-
- GST_INFO_OBJECT (parse,
- "Chose default caps %" GST_PTR_FORMAT " for initial gap", default_caps);
-
- if (sinkcaps)
- gst_caps_unref (sinkcaps);
- gst_caps_unref (caps);
-
- return default_caps;
-
-caps_error:
- {
- if (caps)
- gst_caps_unref (caps);
- if (sinkcaps)
- gst_caps_unref (sinkcaps);
- return NULL;
- }
-}
-
-/* gst_base_parse_sink_event:
- * @pad: #GstPad that received the event.
- * @event: #GstEvent to be handled.
- *
- * Handler for sink pad events.
- *
- * Returns: %TRUE if the event was handled.
- */
-static gboolean
-gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstBaseParse *parse = GST_BASE_PARSE (parent);
- GstBaseParseClass *bclass = GST_BASE_PARSE_GET_CLASS (parse);
- gboolean ret;
-
- ret = bclass->sink_event (parse, event);
-
- return ret;
-}
-
-/* gst_base_parse_sink_event_default:
- * @parse: #GstBaseParse.
- * @event: #GstEvent to be handled.
- *
- * Element-level event handler function.
- *
- * The event will be unreffed only if it has been handled and this
- * function returns %TRUE
- *
- * Returns: %TRUE if the event was handled and not need forwarding.
- */
-static gboolean
-gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
-{
- GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
- gboolean ret = FALSE;
- gboolean forward_immediate = FALSE;
-
- GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event),
- GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_CAPS:
- {
- GstCaps *caps;
-
- gst_event_parse_caps (event, &caps);
- GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
-
- if (klass->set_sink_caps)
- ret = klass->set_sink_caps (parse, caps);
- else
- ret = TRUE;
-
- /* will send our own caps downstream */
- gst_event_unref (event);
- event = NULL;
- break;
- }
- case GST_EVENT_SEGMENT:
- {
- const GstSegment *in_segment;
- GstSegment out_segment;
- gint64 offset = 0, next_dts;
-
- parse->priv->segment_seqnum = gst_event_get_seqnum (event);
- gst_event_parse_segment (event, &in_segment);
- gst_segment_init (&out_segment, GST_FORMAT_TIME);
- out_segment.rate = in_segment->rate;
- out_segment.applied_rate = in_segment->applied_rate;
-
- GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, in_segment);
- GST_DEBUG_OBJECT (parse, "Current segment %" GST_SEGMENT_FORMAT,
- &parse->segment);
-
- parse->priv->upstream_format = in_segment->format;
- if (in_segment->format == GST_FORMAT_BYTES) {
- GstBaseParseSeek *seek = NULL;
- GSList *node;
-
- /* stop time is allowed to be open-ended, but not start & pos */
- offset = in_segment->time;
-
- GST_OBJECT_LOCK (parse);
- for (node = parse->priv->pending_seeks; node; node = node->next) {
- GstBaseParseSeek *tmp = node->data;
-
- if (tmp->offset == offset) {
- seek = tmp;
- break;
- }
- }
- parse->priv->pending_seeks =
- g_slist_remove (parse->priv->pending_seeks, seek);
- GST_OBJECT_UNLOCK (parse);
-
- if (seek) {
- GST_DEBUG_OBJECT (parse,
- "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT,
- seek->accurate ? " accurate" : "", &seek->segment);
-
- out_segment.start = seek->segment.start;
- out_segment.stop = seek->segment.stop;
- out_segment.time = seek->segment.start;
-
- next_dts = seek->start_ts;
- parse->priv->exact_position = seek->accurate;
- g_free (seek);
- } else {
- /* best attempt convert */
- /* as these are only estimates, stop is kept open-ended to avoid
- * premature cutting */
- gst_base_parse_convert (parse, GST_FORMAT_BYTES, in_segment->start,
- GST_FORMAT_TIME, (gint64 *) & next_dts);
-
- out_segment.start = next_dts;
- out_segment.stop = GST_CLOCK_TIME_NONE;
- out_segment.time = next_dts;
-
- parse->priv->exact_position = (in_segment->start == 0);
- }
-
- gst_event_unref (event);
-
- event = gst_event_new_segment (&out_segment);
- gst_event_set_seqnum (event, parse->priv->segment_seqnum);
-
- GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. %"
- GST_SEGMENT_FORMAT, in_segment);
-
- } else if (in_segment->format != GST_FORMAT_TIME) {
- /* Unknown incoming segment format. Output a default open-ended
- * TIME segment */
- gst_event_unref (event);
-
- out_segment.start = 0;
- out_segment.stop = GST_CLOCK_TIME_NONE;
- out_segment.time = 0;
-
- event = gst_event_new_segment (&out_segment);
- gst_event_set_seqnum (event, parse->priv->segment_seqnum);
-
- next_dts = 0;
- } else {
- /* not considered BYTE seekable if it is talking to us in TIME,
- * whatever else it might claim */
- parse->priv->upstream_seekable = FALSE;
- next_dts = GST_CLOCK_TIME_NONE;
- gst_event_copy_segment (event, &out_segment);
- }
-
- GST_DEBUG_OBJECT (parse, "OUT segment %" GST_SEGMENT_FORMAT,
- &out_segment);
- memcpy (&parse->segment, &out_segment, sizeof (GstSegment));
-
- /*
- gst_segment_set_newsegment (&parse->segment, update, rate,
- applied_rate, format, start, stop, start);
- */
-
- ret = TRUE;
-
- /* save the segment for later, right before we push a new buffer so that
- * the caps are fixed and the next linked element can receive
- * the segment but finish the current segment */
- GST_DEBUG_OBJECT (parse, "draining current segment");
- if (in_segment->rate > 0.0)
- gst_base_parse_drain (parse);
- else
- gst_base_parse_finish_fragment (parse, FALSE);
- gst_adapter_clear (parse->priv->adapter);
-
- parse->priv->offset = offset;
- parse->priv->sync_offset = offset;
- parse->priv->next_dts = next_dts;
- parse->priv->next_pts = GST_CLOCK_TIME_NONE;
- parse->priv->last_pts = GST_CLOCK_TIME_NONE;
- parse->priv->last_dts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_dts_from_pts = FALSE;
- parse->priv->discont = TRUE;
- parse->priv->seen_keyframe = FALSE;
- parse->priv->skip = 0;
- break;
- }
-
- case GST_EVENT_SEGMENT_DONE:
- /* need to drain now, rather than upon a new segment,
- * since that would have SEGMENT_DONE come before potential
- * delayed last part of the current segment */
- GST_DEBUG_OBJECT (parse, "draining current segment");
- if (parse->segment.rate > 0.0)
- gst_base_parse_drain (parse);
- else
- gst_base_parse_finish_fragment (parse, FALSE);
- /* Also forward event immediately, there might be no new data
- * coming afterwards that would allow us to forward it later */
- forward_immediate = TRUE;
- break;
-
- case GST_EVENT_FLUSH_START:
- GST_OBJECT_LOCK (parse);
- parse->priv->flushing = TRUE;
- GST_OBJECT_UNLOCK (parse);
- break;
-
- case GST_EVENT_FLUSH_STOP:
- gst_adapter_clear (parse->priv->adapter);
- gst_base_parse_clear_queues (parse);
- parse->priv->flushing = FALSE;
- parse->priv->discont = TRUE;
- parse->priv->last_pts = GST_CLOCK_TIME_NONE;
- parse->priv->last_dts = GST_CLOCK_TIME_NONE;
- parse->priv->new_frame = TRUE;
- parse->priv->skip = 0;
-
- forward_immediate = TRUE;
- break;
-
- case GST_EVENT_EOS:
- if (parse->segment.rate > 0.0)
- gst_base_parse_drain (parse);
- else
- gst_base_parse_finish_fragment (parse, TRUE);
-
- /* If we STILL have zero frames processed, fire an error */
- if (parse->priv->framecount == 0 && !parse->priv->saw_gaps &&
- !parse->priv->first_buffer) {
- GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
- ("No valid frames found before end of stream"), (NULL));
- }
-
- if (!parse->priv->saw_gaps
- && parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) {
- /* We've not posted bitrate tags yet - do so now */
- gst_base_parse_queue_tag_event_update (parse);
- }
-
- /* newsegment and other serialized events before eos */
- gst_base_parse_push_pending_events (parse);
-
- forward_immediate = TRUE;
- break;
- case GST_EVENT_CUSTOM_DOWNSTREAM:{
- /* FIXME: Code duplicated from libgstvideo because core can't depend on -base */
-#ifndef GST_VIDEO_EVENT_STILL_STATE_NAME
-#define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
-#endif
-
- const GstStructure *s;
- gboolean ev_still_state;
-
- s = gst_event_get_structure (event);
- if (s != NULL &&
- gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME) &&
- gst_structure_get_boolean (s, "still-state", &ev_still_state)) {
- if (ev_still_state) {
- GST_DEBUG_OBJECT (parse, "draining current data for still-frame");
- if (parse->segment.rate > 0.0)
- gst_base_parse_drain (parse);
- else
- gst_base_parse_finish_fragment (parse, TRUE);
- }
- forward_immediate = TRUE;
- }
- break;
- }
- case GST_EVENT_GAP:
- {
- GST_DEBUG_OBJECT (parse, "draining current data due to gap event");
-
- /* Ensure we have caps before forwarding the event */
- if (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (parse))) {
- GstCaps *default_caps = NULL;
- if ((default_caps = gst_base_parse_negotiate_default_caps (parse))) {
- GList *l;
- GstEvent *caps_event = gst_event_new_caps (default_caps);
-
- GST_DEBUG_OBJECT (parse,
- "Store caps event to pending list for initial pre-rolling");
-
- /* Events are in decreasing order. Go down the list until we
- * find the first pre-CAPS event and insert our CAPS event there.
- *
- * There should be a SEGMENT event already, which is > CAPS */
- for (l = parse->priv->pending_events; l; l = l->next) {
- GstEvent *e = l->data;
-
- if (GST_EVENT_TYPE (e) < GST_EVENT_CAPS) {
- parse->priv->pending_events =
- g_list_insert_before (parse->priv->pending_events, l,
- caps_event);
- break;
- }
- }
- /* No pending event that is < CAPS, so we have to add it at the very
- * end of the list */
- if (!l) {
- parse->priv->pending_events =
- g_list_append (parse->priv->pending_events, caps_event);
- }
- gst_caps_unref (default_caps);
- } else {
- gst_event_unref (event);
- event = NULL;
- ret = FALSE;
- GST_ELEMENT_ERROR (parse, STREAM, FORMAT, (NULL),
- ("Parser output not negotiated before GAP event."));
- break;
- }
- }
-
- gst_base_parse_push_pending_events (parse);
-
- if (parse->segment.rate > 0.0)
- gst_base_parse_drain (parse);
- else
- gst_base_parse_finish_fragment (parse, TRUE);
- forward_immediate = TRUE;
- parse->priv->saw_gaps = TRUE;
- break;
- }
- case GST_EVENT_TAG:
- {
- GstTagList *tags = NULL;
-
- gst_event_parse_tag (event, &tags);
-
- /* We only care about stream tags here, global tags we just forward */
- if (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_STREAM)
- break;
-
- gst_base_parse_set_upstream_tags (parse, tags);
- gst_base_parse_queue_tag_event_update (parse);
- parse->priv->tags_changed = FALSE;
- gst_event_unref (event);
- event = NULL;
- ret = TRUE;
- break;
- }
- case GST_EVENT_STREAM_START:
- {
- if (parse->priv->pad_mode != GST_PAD_MODE_PULL)
- forward_immediate = TRUE;
-
- gst_base_parse_set_upstream_tags (parse, NULL);
- parse->priv->tags_changed = TRUE;
- break;
- }
- default:
- break;
- }
-
- /* Forward non-serialized events and EOS/FLUSH_STOP immediately.
- * For EOS this is required because no buffer or serialized event
- * will come after EOS and nothing could trigger another
- * _finish_frame() call. *
- * If the subclass handles sending of EOS manually it can return
- * _DROPPED from ::finish() and all other subclasses should have
- * decoded/flushed all remaining data before this
- *
- * For FLUSH_STOP this is required because it is expected
- * to be forwarded immediately and no buffers are queued anyway.
- */
- if (event) {
- if (!GST_EVENT_IS_SERIALIZED (event) || forward_immediate) {
- ret = gst_pad_push_event (parse->srcpad, event);
- } else {
- parse->priv->pending_events =
- g_list_prepend (parse->priv->pending_events, event);
- ret = TRUE;
- }
- }
-
- GST_DEBUG_OBJECT (parse, "event handled");
-
- return ret;
-}
-
-static gboolean
-gst_base_parse_sink_query_default (GstBaseParse * parse, GstQuery * query)
-{
- GstPad *pad;
- gboolean res;
-
- pad = GST_BASE_PARSE_SINK_PAD (parse);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_CAPS:
- {
- GstBaseParseClass *bclass;
-
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
-
- if (bclass->get_sink_caps) {
- GstCaps *caps, *filter;
-
- gst_query_parse_caps (query, &filter);
- caps = bclass->get_sink_caps (parse, filter);
- GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT,
- caps);
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
-
- res = TRUE;
- } else {
- GstCaps *caps, *template_caps, *filter;
-
- gst_query_parse_caps (query, &filter);
- template_caps = gst_pad_get_pad_template_caps (pad);
- if (filter != NULL) {
- caps =
- gst_caps_intersect_full (filter, template_caps,
- GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (template_caps);
- } else {
- caps = template_caps;
- }
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
-
- res = TRUE;
- }
- break;
- }
- default:
- {
- res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
- break;
- }
- }
-
- return res;
-}
-
-static gboolean
-gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstBaseParseClass *bclass;
- GstBaseParse *parse;
- gboolean ret;
-
- parse = GST_BASE_PARSE (parent);
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
-
- GST_DEBUG_OBJECT (parse, "%s query", GST_QUERY_TYPE_NAME (query));
-
- if (bclass->sink_query)
- ret = bclass->sink_query (parse, query);
- else
- ret = FALSE;
-
- GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
- GST_QUERY_TYPE_NAME (query), ret, query);
-
- return ret;
-}
-
-static gboolean
-gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstBaseParseClass *bclass;
- GstBaseParse *parse;
- gboolean ret;
-
- parse = GST_BASE_PARSE (parent);
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
-
- GST_DEBUG_OBJECT (parse, "%s query: %" GST_PTR_FORMAT,
- GST_QUERY_TYPE_NAME (query), query);
-
- if (bclass->src_query)
- ret = bclass->src_query (parse, query);
- else
- ret = FALSE;
-
- GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
- GST_QUERY_TYPE_NAME (query), ret, query);
-
- return ret;
-}
-
-/* gst_base_parse_src_event:
- * @pad: #GstPad that received the event.
- * @event: #GstEvent that was received.
- *
- * Handler for source pad events.
- *
- * Returns: %TRUE if the event was handled.
- */
-static gboolean
-gst_base_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstBaseParse *parse;
- GstBaseParseClass *bclass;
- gboolean ret = TRUE;
-
- parse = GST_BASE_PARSE (parent);
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
-
- GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
- GST_EVENT_TYPE_NAME (event));
-
- if (bclass->src_event)
- ret = bclass->src_event (parse, event);
- else
- gst_event_unref (event);
-
- return ret;
-}
-
-static gboolean
-gst_base_parse_is_seekable (GstBaseParse * parse)
-{
- /* FIXME: could do more here, e.g. check index or just send data from 0
- * in pull mode and let decoder/sink clip */
- return parse->priv->syncable;
-}
-
-/* gst_base_parse_src_event_default:
- * @parse: #GstBaseParse.
- * @event: #GstEvent that was received.
- *
- * Default srcpad event handler.
- *
- * Returns: %TRUE if the event was handled and can be dropped.
- */
-static gboolean
-gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
-{
- gboolean res = FALSE;
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- if (gst_base_parse_is_seekable (parse))
- res = gst_base_parse_handle_seek (parse, event);
- break;
- default:
- res = gst_pad_event_default (parse->srcpad, GST_OBJECT_CAST (parse),
- event);
- break;
- }
- return res;
-}
-
-
-/**
- * gst_base_parse_convert_default:
- * @parse: #GstBaseParse.
- * @src_format: #GstFormat describing the source format.
- * @src_value: Source value to be converted.
- * @dest_format: #GstFormat defining the converted format.
- * @dest_value: (out): Pointer where the conversion result will be put.
- *
- * Default implementation of #GstBaseParseClass::convert.
- *
- * Returns: %TRUE if conversion was successful.
- */
-gboolean
-gst_base_parse_convert_default (GstBaseParse * parse,
- GstFormat src_format,
- gint64 src_value, GstFormat dest_format, gint64 * dest_value)
-{
- gboolean ret = FALSE;
- guint64 bytes, duration;
-
- if (G_UNLIKELY (src_format == dest_format)) {
- *dest_value = src_value;
- return TRUE;
- }
-
- if (G_UNLIKELY (src_value == -1)) {
- *dest_value = -1;
- return TRUE;
- }
-
- if (G_UNLIKELY (src_value == 0)) {
- *dest_value = 0;
- return TRUE;
- }
-
- if (parse->priv->upstream_format != GST_FORMAT_BYTES) {
- /* don't do byte format conversions if we're not really parsing
- * a raw elementary stream, since we don't really have BYTES
- * position / duration info */
- if (src_format == GST_FORMAT_BYTES || dest_format == GST_FORMAT_BYTES)
- goto no_slaved_conversions;
- }
-
- /* need at least some frames */
- if (!parse->priv->framecount)
- goto no_framecount;
-
- duration = parse->priv->acc_duration / GST_MSECOND;
- bytes = parse->priv->bytecount;
-
- if (G_UNLIKELY (!duration || !bytes))
- goto no_duration_bytes;
-
- if (src_format == GST_FORMAT_BYTES) {
- if (dest_format == GST_FORMAT_TIME) {
- /* BYTES -> TIME conversion */
- GST_DEBUG_OBJECT (parse, "converting bytes -> time");
- *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
- *dest_value *= GST_MSECOND;
- GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms",
- *dest_value / GST_MSECOND);
- ret = TRUE;
- } else {
- GST_DEBUG_OBJECT (parse, "converting bytes -> other not implemented");
- }
- } else if (src_format == GST_FORMAT_TIME) {
- if (dest_format == GST_FORMAT_BYTES) {
- GST_DEBUG_OBJECT (parse, "converting time -> bytes");
- *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
- duration);
- GST_DEBUG_OBJECT (parse,
- "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
- src_value / GST_MSECOND, *dest_value);
- ret = TRUE;
- } else {
- GST_DEBUG_OBJECT (parse, "converting time -> other not implemented");
- }
- } else if (src_format == GST_FORMAT_DEFAULT) {
- /* DEFAULT == frame-based */
- if (dest_format == GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (parse, "converting default -> time");
- if (parse->priv->fps_den) {
- *dest_value = gst_util_uint64_scale (src_value,
- GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
- ret = TRUE;
- }
- } else {
- GST_DEBUG_OBJECT (parse, "converting default -> other not implemented");
- }
- } else {
- GST_DEBUG_OBJECT (parse, "conversion not implemented");
- }
- return ret;
-
- /* ERRORS */
-no_framecount:
- {
- GST_DEBUG_OBJECT (parse, "no framecount");
- return FALSE;
- }
-no_duration_bytes:
- {
- GST_DEBUG_OBJECT (parse, "no duration %" G_GUINT64_FORMAT ", bytes %"
- G_GUINT64_FORMAT, duration, bytes);
- return FALSE;
- }
-no_slaved_conversions:
- {
- GST_DEBUG_OBJECT (parse,
- "Can't do format conversions when upstream format is not BYTES");
- return FALSE;
- }
-}
-
-static void
-gst_base_parse_update_duration (GstBaseParse * parse)
-{
- gint64 ptot, dest_value;
-
- if (!gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &ptot))
- return;
-
- if (!gst_base_parse_convert (parse, GST_FORMAT_BYTES, ptot,
- GST_FORMAT_TIME, &dest_value))
- return;
-
- /* inform if duration changed, but try to avoid spamming */
- parse->priv->estimated_drift += dest_value - parse->priv->estimated_duration;
-
- parse->priv->estimated_duration = dest_value;
- GST_LOG_OBJECT (parse,
- "updated estimated duration to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (dest_value));
-
- if (parse->priv->estimated_drift > GST_SECOND ||
- parse->priv->estimated_drift < -GST_SECOND) {
- gst_element_post_message (GST_ELEMENT (parse),
- gst_message_new_duration_changed (GST_OBJECT (parse)));
- parse->priv->estimated_drift = 0;
- }
-}
-
-/* gst_base_parse_update_bitrates:
- * @parse: #GstBaseParse.
- * @buffer: Current frame as a #GstBuffer
- *
- * Keeps track of the minimum and maximum bitrates, and also maintains a
- * running average bitrate of the stream so far.
- */
-static void
-gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- guint64 data_len, frame_dur;
- gint overhead;
- guint frame_bitrate;
- guint64 frame_bitrate64;
- GstBuffer *buffer = frame->buffer;
-
- overhead = frame->overhead;
- if (overhead == -1)
- return;
-
- data_len = gst_buffer_get_size (buffer) - overhead;
- parse->priv->data_bytecount += data_len;
-
- /* duration should be valid by now,
- * either set by subclass or maybe based on fps settings */
- if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) {
- guint64 avg_bitrate;
-
- /* Calculate duration of a frame from buffer properties */
- frame_dur = GST_BUFFER_DURATION (buffer);
- avg_bitrate = gst_util_uint64_scale (GST_SECOND,
- 8 * parse->priv->data_bytecount, parse->priv->acc_duration);
-
- if (avg_bitrate > G_MAXUINT)
- return;
-
- parse->priv->avg_bitrate = (guint) avg_bitrate;
- } else {
- /* No way to figure out frame duration (is this even possible?) */
- return;
- }
-
- /* override if subclass provided bitrate, e.g. metadata based */
- if (parse->priv->bitrate) {
- parse->priv->avg_bitrate = parse->priv->bitrate;
- /* spread this (confirmed) info ASAP */
- if (parse->priv->post_avg_bitrate &&
- parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate)
- parse->priv->tags_changed = TRUE;
- }
-
- if (!frame_dur)
- return;
-
- frame_bitrate64 = gst_util_uint64_scale (GST_SECOND, 8 * data_len, frame_dur);
-
- if (frame_bitrate64 > G_MAXUINT)
- return;
-
- frame_bitrate = (guint) frame_bitrate64;
-
- GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate,
- parse->priv->avg_bitrate);
-
- if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE)
- return;
-
- if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE &&
- (parse->priv->post_min_bitrate || parse->priv->post_avg_bitrate
- || parse->priv->post_max_bitrate))
- parse->priv->tags_changed = TRUE;
-
- if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) {
- if (frame_bitrate < parse->priv->min_bitrate) {
- parse->priv->min_bitrate = frame_bitrate;
- if (parse->priv->post_min_bitrate)
- parse->priv->tags_changed = TRUE;
- }
-
- if (frame_bitrate > parse->priv->max_bitrate) {
- parse->priv->max_bitrate = frame_bitrate;
- if (parse->priv->post_max_bitrate)
- parse->priv->tags_changed = TRUE;
- }
-
- /* Only update the tag on a 2% change */
- if (parse->priv->post_avg_bitrate && parse->priv->avg_bitrate) {
- guint64 diffprev = gst_util_uint64_scale (100,
- ABSDIFF (parse->priv->avg_bitrate, parse->priv->posted_avg_bitrate),
- parse->priv->avg_bitrate);
- if (diffprev >= UPDATE_THRESHOLD)
- parse->priv->tags_changed = TRUE;
- }
- }
-}
-
-/**
- * gst_base_parse_add_index_entry:
- * @parse: #GstBaseParse.
- * @offset: offset of entry
- * @ts: timestamp associated with offset
- * @key: whether entry refers to keyframe
- * @force: add entry disregarding sanity checks
- *
- * Adds an entry to the index associating @offset to @ts. It is recommended
- * to only add keyframe entries. @force allows to bypass checks, such as
- * whether the stream is (upstream) seekable, another entry is already "close"
- * to the new entry, etc.
- *
- * Returns: #gboolean indicating whether entry was added
- */
-gboolean
-gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
- GstClockTime ts, gboolean key, gboolean force)
-{
- gboolean ret = FALSE;
- GstIndexAssociation associations[2];
-
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (ts), FALSE);
-
- GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT
- " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset);
-
- if (G_LIKELY (!force)) {
-
- if (!parse->priv->upstream_seekable) {
- GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding");
- goto exit;
- }
-
- /* FIXME need better helper data structure that handles these issues
- * related to ongoing collecting of index entries */
- if (parse->priv->index_last_offset + parse->priv->idx_byte_interval >=
- (gint64) offset) {
- GST_LOG_OBJECT (parse,
- "already have entries up to offset 0x%08" G_GINT64_MODIFIER "x",
- parse->priv->index_last_offset + parse->priv->idx_byte_interval);
- goto exit;
- }
-
- if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) &&
- GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) <
- parse->priv->idx_interval) {
- GST_LOG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (parse->priv->index_last_ts));
- goto exit;
- }
-
- /* if last is not really the last one */
- if (!parse->priv->index_last_valid) {
- GstClockTime prev_ts;
-
- gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts);
- if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) {
- GST_LOG_OBJECT (parse,
- "entry too close to existing entry %" GST_TIME_FORMAT,
- GST_TIME_ARGS (prev_ts));
- parse->priv->index_last_offset = offset;
- parse->priv->index_last_ts = ts;
- goto exit;
- }
- }
- }
-
- associations[0].format = GST_FORMAT_TIME;
- associations[0].value = ts;
- associations[1].format = GST_FORMAT_BYTES;
- associations[1].value = offset;
-
- /* index might change on-the-fly, although that would be nutty app ... */
- GST_BASE_PARSE_INDEX_LOCK (parse);
- gst_index_add_associationv (parse->priv->index, parse->priv->index_id,
- (key) ? GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT :
- GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT, 2,
- (const GstIndexAssociation *) &associations);
- GST_BASE_PARSE_INDEX_UNLOCK (parse);
-
- if (key) {
- parse->priv->index_last_offset = offset;
- parse->priv->index_last_ts = ts;
- }
-
- ret = TRUE;
-
-exit:
- return ret;
-}
-
-/* check for seekable upstream, above and beyond a mere query */
-static void
-gst_base_parse_check_seekability (GstBaseParse * parse)
-{
- GstQuery *query;
- gboolean seekable = FALSE;
- gint64 start = -1, stop = -1;
- guint idx_interval = 0;
- guint64 idx_byte_interval = 0;
-
- query = gst_query_new_seeking (GST_FORMAT_BYTES);
- if (!gst_pad_peer_query (parse->sinkpad, query)) {
- GST_DEBUG_OBJECT (parse, "seeking query failed");
- goto done;
- }
-
- gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
-
- /* try harder to query upstream size if we didn't get it the first time */
- if (seekable && stop == -1) {
- GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
- gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &stop);
- }
-
- /* if upstream doesn't know the size, it's likely that it's not seekable in
- * practice even if it technically may be seekable */
- if (seekable && (start != 0 || stop <= start)) {
- GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
- seekable = FALSE;
- }
-
- /* let's not put every single frame into our index */
- if (seekable) {
- if (stop < 10 * 1024 * 1024)
- idx_interval = 100;
- else if (stop < 100 * 1024 * 1024)
- idx_interval = 500;
- else
- idx_interval = 1000;
-
- /* ensure that even for large files (e.g. very long audio files), the index
- * stays reasonably-size, with some arbitrary limit to the total number of
- * index entries */
- idx_byte_interval = (stop - start) / MAX_INDEX_ENTRIES;
- GST_DEBUG_OBJECT (parse,
- "Limiting index entries to %d, indexing byte interval %"
- G_GUINT64_FORMAT " bytes", MAX_INDEX_ENTRIES, idx_byte_interval);
- }
-
-done:
- gst_query_unref (query);
-
- GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
- G_GUINT64_FORMAT ")", seekable, start, stop);
- parse->priv->upstream_seekable = seekable;
- parse->priv->upstream_size = seekable ? stop : 0;
-
- GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval);
- parse->priv->idx_interval = idx_interval * GST_MSECOND;
- parse->priv->idx_byte_interval = idx_byte_interval;
-}
-
-/* some misc checks on upstream */
-static void
-gst_base_parse_check_upstream (GstBaseParse * parse)
-{
- gint64 stop;
-
- if (gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_TIME, &stop))
- if (GST_CLOCK_TIME_IS_VALID (stop) && stop) {
- /* upstream has one, accept it also, and no further updates */
- gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0);
- parse->priv->upstream_has_duration = TRUE;
- }
-
- GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d",
- parse->priv->upstream_has_duration);
-}
-
-/* checks src caps to determine if dealing with audio or video */
-/* TODO maybe forego automagic stuff and let subclass configure it ? */
-static void
-gst_base_parse_check_media (GstBaseParse * parse)
-{
- GstCaps *caps;
- GstStructure *s;
-
- caps = gst_pad_get_current_caps (parse->srcpad);
- if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) {
- parse->priv->is_video =
- g_str_has_prefix (gst_structure_get_name (s), "video");
- } else {
- /* historical default */
- parse->priv->is_video = FALSE;
- }
- if (caps)
- gst_caps_unref (caps);
-
- parse->priv->checked_media = TRUE;
- GST_DEBUG_OBJECT (parse, "media is video: %d", parse->priv->is_video);
-}
-
-/* takes ownership of frame */
-static void
-gst_base_parse_queue_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
- /* frame allocated on the heap, we can just take ownership */
- g_queue_push_tail (&parse->priv->queued_frames, frame);
- GST_TRACE ("queued frame %p", frame);
- } else {
- GstBaseParseFrame *copy;
-
- /* probably allocated on the stack, must make a proper copy */
- copy = gst_base_parse_frame_copy (frame);
- g_queue_push_tail (&parse->priv->queued_frames, copy);
- GST_TRACE ("queued frame %p (copy of %p)", copy, frame);
- gst_base_parse_frame_free (frame);
- }
-}
-
-/* makes sure that @buf is properly prepared and decorated for passing
- * to baseclass, and an equally setup frame is returned setup with @buf.
- * Takes ownership of @buf. */
-static GstBaseParseFrame *
-gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
-{
- GstBaseParseFrame *frame = NULL;
-
- buffer = gst_buffer_make_writable (buffer);
-
- GST_LOG_OBJECT (parse,
- "preparing frame at offset %" G_GUINT64_FORMAT
- " (%#" G_GINT64_MODIFIER "x) of size %" G_GSIZE_FORMAT,
- GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer),
- gst_buffer_get_size (buffer));
-
- GST_BUFFER_OFFSET (buffer) = parse->priv->offset;
-
- gst_base_parse_update_flags (parse);
-
- frame = gst_base_parse_frame_new (buffer, 0, 0);
- gst_buffer_unref (buffer);
- gst_base_parse_update_frame (parse, frame);
-
- /* clear flags for next frame */
- parse->priv->discont = FALSE;
- parse->priv->new_frame = FALSE;
-
- /* use default handler to provide initial (upstream) metadata */
- gst_base_parse_parse_frame (parse, frame);
-
- return frame;
-}
-
-/* Wraps buffer in a frame and dispatches to subclass.
- * Also manages data skipping and offset handling (including adapter flushing).
- * Takes ownership of @buffer */
-static GstFlowReturn
-gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
- gint * skip, gint * flushed)
-{
- GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
- GstBaseParseFrame *frame;
- GstFlowReturn ret;
-
- g_return_val_if_fail (skip != NULL || flushed != NULL, GST_FLOW_ERROR);
-
- GST_LOG_OBJECT (parse,
- "handling buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT
- ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
- gst_buffer_get_size (buffer), GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
-
- /* track what is being flushed during this single round of frame processing */
- parse->priv->flushed = 0;
- *skip = 0;
-
- /* make it easy for _finish_frame to pick up input data */
- if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
- gst_buffer_ref (buffer);
- gst_adapter_push (parse->priv->adapter, buffer);
- }
-
- frame = gst_base_parse_prepare_frame (parse, buffer);
- ret = klass->handle_frame (parse, frame, skip);
-
- *flushed = parse->priv->flushed;
-
- GST_LOG_OBJECT (parse, "handle_frame skipped %d, flushed %d",
- *skip, *flushed);
-
- /* subclass can only do one of these, or semantics are too unclear */
- g_assert (*skip == 0 || *flushed == 0);
-
- /* track skipping */
- if (*skip > 0) {
- GstClockTime pts, dts;
- GstBuffer *outbuf;
-
- GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", *skip);
- if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) {
- /* reverse playback, and no frames found yet, so we are skipping
- * the leading part of a fragment, which may form the tail of
- * fragment coming later, hopefully subclass skips efficiently ... */
- pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
- dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
- outbuf = gst_adapter_take_buffer (parse->priv->adapter, *skip);
- outbuf = gst_buffer_make_writable (outbuf);
- GST_BUFFER_PTS (outbuf) = pts;
- GST_BUFFER_DTS (outbuf) = dts;
- parse->priv->buffers_head =
- g_slist_prepend (parse->priv->buffers_head, outbuf);
- outbuf = NULL;
- } else {
- /* If we're asked to skip more than is available in the adapter,
- we need to remember what we need to skip for next iteration */
- gsize av = gst_adapter_available (parse->priv->adapter);
- GST_DEBUG ("Asked to skip %u (%" G_GSIZE_FORMAT " available)", *skip, av);
- if (av >= *skip) {
- gst_adapter_flush (parse->priv->adapter, *skip);
- } else {
- GST_DEBUG
- ("This is more than available, flushing %" G_GSIZE_FORMAT
- ", storing %u to skip", av, (guint) (*skip - av));
- parse->priv->skip = *skip - av;
- gst_adapter_flush (parse->priv->adapter, av);
- *skip = av;
- }
- }
- if (!parse->priv->discont)
- parse->priv->sync_offset = parse->priv->offset;
- parse->priv->offset += *skip;
- parse->priv->discont = TRUE;
- /* check for indefinite skipping */
- if (ret == GST_FLOW_OK)
- ret = gst_base_parse_check_sync (parse);
- }
-
- parse->priv->offset += *flushed;
-
- if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
- gst_adapter_clear (parse->priv->adapter);
- }
-
- if (*skip == 0 && *flushed == 0) {
- /* Carry over discont if we need more data */
- if (GST_BUFFER_IS_DISCONT (frame->buffer))
- parse->priv->discont = TRUE;
- }
-
- gst_base_parse_frame_free (frame);
-
- return ret;
-}
-
-/* gst_base_parse_push_pending_events:
- * @parse: #GstBaseParse
- *
- * Pushes the pending events
- */
-static void
-gst_base_parse_push_pending_events (GstBaseParse * parse)
-{
- if (G_UNLIKELY (parse->priv->pending_events)) {
- GList *r = g_list_reverse (parse->priv->pending_events);
- GList *l;
-
- parse->priv->pending_events = NULL;
- for (l = r; l != NULL; l = l->next) {
- gst_pad_push_event (parse->srcpad, GST_EVENT_CAST (l->data));
- }
- g_list_free (r);
- }
-}
-
-/* gst_base_parse_handle_and_push_frame:
- * @parse: #GstBaseParse.
- * @klass: #GstBaseParseClass.
- * @frame: (transfer full): a #GstBaseParseFrame
- *
- * Parses the frame from given buffer and pushes it forward. Also performs
- * timestamp handling and checks the segment limits.
- *
- * This is called with srcpad STREAM_LOCK held.
- *
- * Returns: #GstFlowReturn
- */
-static GstFlowReturn
-gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame)
-{
- gint64 offset;
- GstBuffer *buffer;
-
- g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
-
- buffer = frame->buffer;
- offset = frame->offset;
-
- /* check if subclass/format can provide ts.
- * If so, that allows and enables extra seek and duration determining options */
- if (G_UNLIKELY (parse->priv->first_frame_offset < 0)) {
- if (GST_BUFFER_PTS_IS_VALID (buffer) && parse->priv->has_timing_info
- && parse->priv->pad_mode == GST_PAD_MODE_PULL) {
- parse->priv->first_frame_offset = offset;
- parse->priv->first_frame_pts = GST_BUFFER_PTS (buffer);
- parse->priv->first_frame_dts = GST_BUFFER_DTS (buffer);
- GST_DEBUG_OBJECT (parse, "subclass provided dts %" GST_TIME_FORMAT
- ", pts %" GST_TIME_FORMAT " for first frame at offset %"
- G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->first_frame_dts),
- GST_TIME_ARGS (parse->priv->first_frame_pts),
- parse->priv->first_frame_offset);
- if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) {
- gint64 off;
- GstClockTime last_ts = G_MAXINT64;
-
- GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine");
- gst_base_parse_locate_time (parse, &last_ts, &off);
- if (GST_CLOCK_TIME_IS_VALID (last_ts))
- gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0);
- }
- } else {
- /* disable further checks */
- parse->priv->first_frame_offset = 0;
- }
- }
-
- /* track upstream time if provided, not subclass' internal notion of it */
- if (parse->priv->upstream_format == GST_FORMAT_TIME) {
- GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_DTS (frame->buffer) = GST_CLOCK_TIME_NONE;
- }
-
- /* interpolating and no valid pts yet,
- * start with dts and carry on from there */
- if (parse->priv->infer_ts && parse->priv->pts_interpolate
- && !GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts))
- parse->priv->next_pts = parse->priv->next_dts;
-
- /* again use default handler to add missing metadata;
- * we may have new information on frame properties */
- gst_base_parse_parse_frame (parse, frame);
-
- parse->priv->next_pts = GST_CLOCK_TIME_NONE;
- if (GST_BUFFER_DTS_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) {
- parse->priv->next_dts =
- GST_BUFFER_DTS (buffer) + GST_BUFFER_DURATION (buffer);
- if (parse->priv->pts_interpolate && GST_BUFFER_PTS_IS_VALID (buffer)) {
- GstClockTime next_pts =
- GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer);
- if (next_pts >= parse->priv->next_dts)
- parse->priv->next_pts = next_pts;
- }
- } else {
- /* we lost track, do not produce bogus time next time around
- * (probably means parser subclass has given up on parsing as well) */
- GST_DEBUG_OBJECT (parse, "no next fallback timestamp");
- parse->priv->next_dts = GST_CLOCK_TIME_NONE;
- }
-
- if (parse->priv->upstream_seekable && parse->priv->exact_position &&
- GST_BUFFER_PTS_IS_VALID (buffer))
- gst_base_parse_add_index_entry (parse, offset,
- GST_BUFFER_PTS (buffer),
- !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE);
-
- /* All OK, push queued frames if there are any */
- if (G_UNLIKELY (!g_queue_is_empty (&parse->priv->queued_frames))) {
- GstBaseParseFrame *queued_frame;
-
- while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) {
- gst_base_parse_push_frame (parse, queued_frame);
- gst_base_parse_frame_free (queued_frame);
- }
- }
-
- return gst_base_parse_push_frame (parse, frame);
-}
-
-/**
- * gst_base_parse_push_frame:
- * @parse: #GstBaseParse.
- * @frame: (transfer none): a #GstBaseParseFrame
- *
- * Pushes the frame's buffer downstream, sends any pending events and
- * does some timestamp and segment handling. Takes ownership of
- * frame's buffer, though caller retains ownership of @frame.
- *
- * This must be called with sinkpad STREAM_LOCK held.
- *
- * Returns: #GstFlowReturn
- */
-GstFlowReturn
-gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstClockTime last_start = GST_CLOCK_TIME_NONE;
- GstClockTime last_stop = GST_CLOCK_TIME_NONE;
- GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
- GstBuffer *buffer;
- gsize size;
-
- g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
-
- GST_TRACE_OBJECT (parse, "pushing frame %p", frame);
-
- buffer = frame->buffer;
-
- GST_LOG_OBJECT (parse,
- "processing buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT
- ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
- gst_buffer_get_size (buffer),
- GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
-
- /* update stats */
- parse->priv->bytecount += frame->size;
- if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
- parse->priv->framecount++;
- if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
- parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
- }
- }
- /* 0 means disabled */
- if (parse->priv->update_interval < 0)
- parse->priv->update_interval = 50;
- else if (parse->priv->update_interval > 0 &&
- (parse->priv->framecount % parse->priv->update_interval) == 0)
- gst_base_parse_update_duration (parse);
-
- if (GST_BUFFER_PTS_IS_VALID (buffer))
- last_start = last_stop = GST_BUFFER_PTS (buffer);
- if (last_start != GST_CLOCK_TIME_NONE
- && GST_BUFFER_DURATION_IS_VALID (buffer))
- last_stop = last_start + GST_BUFFER_DURATION (buffer);
-
- /* should have caps by now */
- if (!gst_pad_has_current_caps (parse->srcpad))
- goto no_caps;
-
- if (G_UNLIKELY (!parse->priv->checked_media)) {
- /* have caps; check identity */
- gst_base_parse_check_media (parse);
- }
-
- if (parse->priv->tags_changed) {
- gst_base_parse_queue_tag_event_update (parse);
- parse->priv->tags_changed = FALSE;
- }
-
- /* Push pending events, including SEGMENT events */
- gst_base_parse_push_pending_events (parse);
-
- /* update bitrates and optionally post corresponding tags
- * (following newsegment) */
- gst_base_parse_update_bitrates (parse, frame);
-
- if (klass->pre_push_frame) {
- ret = klass->pre_push_frame (parse, frame);
- } else {
- frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
- }
-
- /* Push pending events, if there are any new ones
- * like tags added by pre_push_frame */
- if (parse->priv->tags_changed) {
- gst_base_parse_queue_tag_event_update (parse);
- parse->priv->tags_changed = FALSE;
- }
- gst_base_parse_push_pending_events (parse);
-
- /* take final ownership of frame buffer */
- if (frame->out_buffer) {
- buffer = frame->out_buffer;
- frame->out_buffer = NULL;
- gst_buffer_replace (&frame->buffer, NULL);
- } else {
- buffer = frame->buffer;
- frame->buffer = NULL;
- }
-
- /* subclass must play nice */
- g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
-
- size = gst_buffer_get_size (buffer);
-
- parse->priv->seen_keyframe |= parse->priv->is_video &&
- !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
-
- if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) {
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
- GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
- GST_BUFFER_TIMESTAMP (buffer) >
- parse->segment.stop + parse->priv->lead_out_ts) {
- GST_LOG_OBJECT (parse, "Dropped frame, after segment");
- ret = GST_FLOW_EOS;
- } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
- GST_BUFFER_DURATION_IS_VALID (buffer) &&
- GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
- GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
- parse->priv->lead_in_ts < parse->segment.start) {
- if (parse->priv->seen_keyframe) {
- GST_LOG_OBJECT (parse, "Frame before segment, after keyframe");
- ret = GST_FLOW_OK;
- } else {
- GST_LOG_OBJECT (parse, "Dropped frame, before segment");
- ret = GST_BASE_PARSE_FLOW_DROPPED;
- }
- } else {
- ret = GST_FLOW_OK;
- }
- }
-
- if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
- GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) dropped", size);
- if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
- parse->priv->discont = TRUE;
- gst_buffer_unref (buffer);
- ret = GST_FLOW_OK;
- } else if (ret == GST_FLOW_OK) {
- if (parse->segment.rate > 0.0) {
- GST_LOG_OBJECT (parse, "pushing frame (%" G_GSIZE_FORMAT " bytes) now..",
- size);
- ret = gst_pad_push (parse->srcpad, buffer);
- GST_LOG_OBJECT (parse, "frame pushed, flow %s", gst_flow_get_name (ret));
- } else if (!parse->priv->disable_passthrough && parse->priv->passthrough) {
-
- /* in backwards playback mode, if on passthrough we need to push buffers
- * directly without accumulating them into the buffers_queued as baseparse
- * will never check for a DISCONT while on passthrough and those buffers
- * will never be pushed.
- *
- * also, as we are on reverse playback, it might be possible that
- * passthrough might have just been enabled, so make sure to drain the
- * buffers_queued list */
- if (G_UNLIKELY (parse->priv->buffers_queued != NULL)) {
- gst_base_parse_finish_fragment (parse, TRUE);
- ret = gst_base_parse_send_buffers (parse);
- }
-
- if (ret == GST_FLOW_OK) {
- GST_LOG_OBJECT (parse,
- "pushing frame (%" G_GSIZE_FORMAT " bytes) now..", size);
- ret = gst_pad_push (parse->srcpad, buffer);
- GST_LOG_OBJECT (parse, "frame pushed, flow %s",
- gst_flow_get_name (ret));
- } else {
- GST_LOG_OBJECT (parse,
- "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s", size,
- gst_flow_get_name (ret));
- gst_buffer_unref (buffer);
- }
-
- } else {
- GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) queued for now",
- size);
- parse->priv->buffers_queued =
- g_slist_prepend (parse->priv->buffers_queued, buffer);
- ret = GST_FLOW_OK;
- }
- } else {
- GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s",
- size, gst_flow_get_name (ret));
- gst_buffer_unref (buffer);
- /* if we are not sufficiently in control, let upstream decide on EOS */
- if (ret == GST_FLOW_EOS && !parse->priv->disable_passthrough &&
- (parse->priv->passthrough ||
- (parse->priv->pad_mode == GST_PAD_MODE_PUSH &&
- !parse->priv->upstream_seekable)))
- ret = GST_FLOW_OK;
- }
-
- /* Update current running segment position */
- if ((ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED)
- && last_stop != GST_CLOCK_TIME_NONE
- && parse->segment.position < last_stop)
- parse->segment.position = last_stop;
-
- return ret;
-
- /* ERRORS */
-no_caps:
- {
- if (GST_PAD_IS_FLUSHING (parse->srcpad))
- return GST_FLOW_FLUSHING;
-
- GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("No caps set"), (NULL));
- return GST_FLOW_ERROR;
- }
-}
-
-/**
- * gst_base_parse_finish_frame:
- * @parse: a #GstBaseParse
- * @frame: a #GstBaseParseFrame
- * @size: consumed input data represented by frame
- *
- * Collects parsed data and pushes this downstream.
- * Source pad caps must be set when this is called.
- *
- * If @frame's out_buffer is set, that will be used as subsequent frame data.
- * Otherwise, @size samples will be taken from the input and used for output,
- * and the output's metadata (timestamps etc) will be taken as (optionally)
- * set by the subclass on @frame's (input) buffer (which is otherwise
- * ignored for any but the above purpose/information).
- *
- * Note that the latter buffer is invalidated by this call, whereas the
- * caller retains ownership of @frame.
- *
- * Returns: a #GstFlowReturn that should be escalated to caller (of caller)
- */
-GstFlowReturn
-gst_base_parse_finish_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
- gint size)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (size > 0 || frame->out_buffer, GST_FLOW_ERROR);
- g_return_val_if_fail (gst_adapter_available (parse->priv->adapter) >= size,
- GST_FLOW_ERROR);
-
- GST_LOG_OBJECT (parse, "finished frame at offset %" G_GUINT64_FORMAT ", "
- "flushing size %d", frame->offset, size);
-
- /* some one-time start-up */
- if (G_UNLIKELY (parse->priv->framecount == 0)) {
- gst_base_parse_check_seekability (parse);
- gst_base_parse_check_upstream (parse);
- }
-
- parse->priv->flushed += size;
-
- if (parse->priv->scanning && frame->buffer) {
- if (!parse->priv->scanned_frame) {
- parse->priv->scanned_frame = gst_base_parse_frame_copy (frame);
- }
- goto exit;
- }
-
- /* either PUSH or PULL mode arranges for adapter data */
- /* ensure output buffer */
- if (!frame->out_buffer) {
- GstBuffer *src, *dest;
-
- frame->out_buffer = gst_adapter_take_buffer (parse->priv->adapter, size);
- dest = frame->out_buffer;
- src = frame->buffer;
- GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
- GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
- GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
- GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
- GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
- GST_MINI_OBJECT_FLAGS (dest) = GST_MINI_OBJECT_FLAGS (src);
- } else {
- gst_adapter_flush (parse->priv->adapter, size);
- }
-
- /* use as input for subsequent processing */
- gst_buffer_replace (&frame->buffer, frame->out_buffer);
- gst_buffer_unref (frame->out_buffer);
- frame->out_buffer = NULL;
-
- /* mark input size consumed */
- frame->size = size;
-
- /* subclass might queue frames/data internally if it needs more
- * frames to decide on the format, or might request us to queue here. */
- if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_DROP) {
- gst_buffer_replace (&frame->buffer, NULL);
- goto exit;
- } else if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_QUEUE) {
- GstBaseParseFrame *copy;
-
- copy = gst_base_parse_frame_copy (frame);
- copy->flags &= ~GST_BASE_PARSE_FRAME_FLAG_QUEUE;
- gst_base_parse_queue_frame (parse, copy);
- goto exit;
- }
-
- ret = gst_base_parse_handle_and_push_frame (parse, frame);
-
-exit:
- return ret;
-}
-
-/**
- * gst_base_parse_drain:
- * @parse: a #GstBaseParse
- *
- * Drains the adapter until it is empty. It decreases the min_frame_size to
- * match the current adapter size and calls chain method until the adapter
- * is emptied or chain returns with error.
- *
- * Since: 1.12
- */
-void
-gst_base_parse_drain (GstBaseParse * parse)
-{
- guint avail;
-
- GST_DEBUG_OBJECT (parse, "draining");
- parse->priv->drain = TRUE;
-
- for (;;) {
- avail = gst_adapter_available (parse->priv->adapter);
- if (!avail)
- break;
-
- if (gst_base_parse_chain (parse->sinkpad, GST_OBJECT_CAST (parse),
- NULL) != GST_FLOW_OK) {
- break;
- }
-
- /* nothing changed, maybe due to truncated frame; break infinite loop */
- if (avail == gst_adapter_available (parse->priv->adapter)) {
- GST_DEBUG_OBJECT (parse, "no change during draining; flushing");
- gst_adapter_clear (parse->priv->adapter);
- }
- }
-
- parse->priv->drain = FALSE;
-}
-
-/* gst_base_parse_send_buffers
- *
- * Sends buffers collected in send_buffers downstream, and ensures that list
- * is empty at the end (errors or not).
- */
-static GstFlowReturn
-gst_base_parse_send_buffers (GstBaseParse * parse)
-{
- GSList *send = NULL;
- GstBuffer *buf;
- GstFlowReturn ret = GST_FLOW_OK;
- gboolean first = TRUE;
-
- send = parse->priv->buffers_send;
-
- /* send buffers */
- while (send) {
- buf = GST_BUFFER_CAST (send->data);
- GST_LOG_OBJECT (parse, "pushing buffer %p, dts %"
- GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
- ", offset %" G_GINT64_FORMAT, buf,
- GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf));
-
- /* Make sure the first buffer is always DISCONT. If we split
- * GOPs inside the parser this is otherwise not guaranteed */
- if (first) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- first = FALSE;
- } else {
- /* likewise, subsequent buffers should never have DISCONT
- * according to the "reverse fragment protocol", or such would
- * confuse a downstream decoder
- * (could be DISCONT due to aggregating upstream fragments by parsing) */
- GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
- }
-
- /* iterate output queue an push downstream */
- ret = gst_pad_push (parse->srcpad, buf);
- send = g_slist_delete_link (send, send);
-
- /* clear any leftover if error */
- if (G_UNLIKELY (ret != GST_FLOW_OK)) {
- while (send) {
- buf = GST_BUFFER_CAST (send->data);
- gst_buffer_unref (buf);
- send = g_slist_delete_link (send, send);
- }
- }
- }
-
- parse->priv->buffers_send = send;
-
- return ret;
-}
-
-/* gst_base_parse_start_fragment:
- *
- * Prepares for processing a reverse playback (forward) fragment
- * by (re)setting proper state variables.
- */
-static GstFlowReturn
-gst_base_parse_start_fragment (GstBaseParse * parse)
-{
- GST_LOG_OBJECT (parse, "starting fragment");
-
- /* invalidate so no fall-back timestamping is performed;
- * ok if taken from subclass or upstream */
- parse->priv->next_pts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
- parse->priv->next_dts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
- parse->priv->prev_dts_from_pts = FALSE;
- /* prevent it hanging around stop all the time */
- parse->segment.position = GST_CLOCK_TIME_NONE;
- /* mark next run */
- parse->priv->discont = TRUE;
-
- /* head of previous fragment is now pending tail of current fragment */
- parse->priv->buffers_pending = parse->priv->buffers_head;
- parse->priv->buffers_head = NULL;
-
- return GST_FLOW_OK;
-}
-
-
-/* gst_base_parse_finish_fragment:
- *
- * Processes a reverse playback (forward) fragment:
- * - append head of last fragment that was skipped to current fragment data
- * - drain the resulting current fragment data (i.e. repeated chain)
- * - add time/duration (if needed) to frames queued by chain
- * - push queued data
- */
-static GstFlowReturn
-gst_base_parse_finish_fragment (GstBaseParse * parse, gboolean prev_head)
-{
- GstBuffer *buf;
- GstFlowReturn ret = GST_FLOW_OK;
- gboolean seen_key = FALSE, seen_delta = FALSE;
-
- GST_LOG_OBJECT (parse, "finishing fragment");
-
- /* restore order */
- parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending);
- while (parse->priv->buffers_pending) {
- buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data);
- if (prev_head) {
- GST_LOG_OBJECT (parse, "adding pending buffer (size %" G_GSIZE_FORMAT ")",
- gst_buffer_get_size (buf));
- gst_adapter_push (parse->priv->adapter, buf);
- } else {
- GST_LOG_OBJECT (parse, "discarding head buffer");
- gst_buffer_unref (buf);
- }
- parse->priv->buffers_pending =
- g_slist_delete_link (parse->priv->buffers_pending,
- parse->priv->buffers_pending);
- }
-
- /* chain looks for frames and queues resulting ones (in stead of pushing) */
- /* initial skipped data is added to buffers_pending */
- gst_base_parse_drain (parse);
-
- if (parse->priv->buffers_send) {
- buf = GST_BUFFER_CAST (parse->priv->buffers_send->data);
- seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
- }
-
- /* add metadata (if needed to queued buffers */
- GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (parse->priv->last_pts));
- while (parse->priv->buffers_queued) {
- buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data);
-
- /* no touching if upstream or parsing provided time */
- if (GST_BUFFER_PTS_IS_VALID (buf)) {
- GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
- } else if (GST_BUFFER_DURATION_IS_VALID (buf)) {
- if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_pts)) {
- if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_pts))
- parse->priv->last_pts -= GST_BUFFER_DURATION (buf);
- else
- parse->priv->last_pts = 0;
- GST_BUFFER_PTS (buf) = parse->priv->last_pts;
- GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
- }
- if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_dts)) {
- if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_dts))
- parse->priv->last_dts -= GST_BUFFER_DURATION (buf);
- else
- parse->priv->last_dts = 0;
- GST_BUFFER_DTS (buf) = parse->priv->last_dts;
- GST_LOG_OBJECT (parse, "applied dts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_DTS (buf)));
- }
- } else {
- /* no idea, very bad */
- GST_WARNING_OBJECT (parse, "could not determine time for buffer");
- }
-
- parse->priv->last_pts = GST_BUFFER_PTS (buf);
- parse->priv->last_dts = GST_BUFFER_DTS (buf);
-
- /* reverse order for ascending sending */
- /* send downstream at keyframe not preceded by a keyframe
- * (e.g. that should identify start of collection of IDR nals) */
- if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
- if (seen_key) {
- ret = gst_base_parse_send_buffers (parse);
- /* if a problem, throw all to sending */
- if (ret != GST_FLOW_OK) {
- parse->priv->buffers_send =
- g_slist_reverse (parse->priv->buffers_queued);
- parse->priv->buffers_queued = NULL;
- break;
- }
- seen_key = FALSE;
- }
- seen_delta = TRUE;
- } else {
- seen_key = TRUE;
- }
-
- parse->priv->buffers_send =
- g_slist_prepend (parse->priv->buffers_send, buf);
- parse->priv->buffers_queued =
- g_slist_delete_link (parse->priv->buffers_queued,
- parse->priv->buffers_queued);
- }
-
- /* audio may have all marked as keyframe, so arrange to send here. Also
- * we might have ended the loop above on a keyframe, in which case we
- * should */
- if (!seen_delta || seen_key)
- ret = gst_base_parse_send_buffers (parse);
-
- /* any trailing unused no longer usable (ideally none) */
- if (G_UNLIKELY (gst_adapter_available (parse->priv->adapter))) {
- GST_DEBUG_OBJECT (parse, "discarding %" G_GSIZE_FORMAT " trailing bytes",
- gst_adapter_available (parse->priv->adapter));
- gst_adapter_clear (parse->priv->adapter);
- }
-
- return ret;
-}
-
-/* small helper that checks whether we have been trying to resync too long */
-static inline GstFlowReturn
-gst_base_parse_check_sync (GstBaseParse * parse)
-{
- if (G_UNLIKELY (parse->priv->discont &&
- parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) {
- GST_ELEMENT_ERROR (parse, STREAM, DECODE,
- ("Failed to parse stream"), (NULL));
- return GST_FLOW_ERROR;
- }
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_base_parse_process_streamheader (GstBaseParse * parse)
-{
- GstCaps *caps;
- GstStructure *str;
- const GValue *value;
- GstFlowReturn ret = GST_FLOW_OK;
-
- caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
- if (caps == NULL)
- goto notfound;
-
- str = gst_caps_get_structure (caps, 0);
- value = gst_structure_get_value (str, "streamheader");
- if (value == NULL)
- goto notfound;
-
- GST_DEBUG_OBJECT (parse, "Found streamheader field on input caps");
-
- if (GST_VALUE_HOLDS_ARRAY (value)) {
- gint i;
- gsize len = gst_value_array_get_size (value);
-
- for (i = 0; i < len; i++) {
- GstBuffer *buffer =
- gst_value_get_buffer (gst_value_array_get_value (value, i));
- ret =
- gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
- GST_OBJECT_CAST (parse), gst_buffer_ref (buffer));
- }
-
- } else if (GST_VALUE_HOLDS_BUFFER (value)) {
- GstBuffer *buffer = gst_value_get_buffer (value);
- ret =
- gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
- GST_OBJECT_CAST (parse), gst_buffer_ref (buffer));
- }
-
- gst_caps_unref (caps);
-
- return ret;
-
-notfound:
- {
- if (caps) {
- gst_caps_unref (caps);
- }
-
- GST_DEBUG_OBJECT (parse, "No streamheader on caps");
- return GST_FLOW_OK;
- }
-}
-
-static GstFlowReturn
-gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
-{
- GstBaseParseClass *bclass;
- GstBaseParse *parse;
- GstFlowReturn ret = GST_FLOW_OK;
- GstFlowReturn old_ret = GST_FLOW_OK;
- GstBuffer *tmpbuf = NULL;
- guint fsize = 1;
- gint skip = -1;
- guint min_size, av;
- GstClockTime pts, dts;
-
- parse = GST_BASE_PARSE (parent);
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
- GST_DEBUG_OBJECT (parent, "chain");
-
- /* early out for speed, if we need to skip */
- if (buffer && GST_BUFFER_IS_DISCONT (buffer))
- parse->priv->skip = 0;
- if (parse->priv->skip > 0) {
- gsize bsize = gst_buffer_get_size (buffer);
- GST_DEBUG ("Got %" G_GSIZE_FORMAT " buffer, need to skip %u", bsize,
- parse->priv->skip);
- if (parse->priv->skip >= bsize) {
- parse->priv->skip -= bsize;
- GST_DEBUG ("All the buffer is skipped");
- parse->priv->offset += bsize;
- parse->priv->sync_offset = parse->priv->offset;
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
- buffer = gst_buffer_make_writable (buffer);
- gst_buffer_resize (buffer, parse->priv->skip, bsize - parse->priv->skip);
- parse->priv->offset += parse->priv->skip;
- GST_DEBUG ("Done skipping, we have %u left on this buffer",
- (unsigned) (bsize - parse->priv->skip));
- parse->priv->skip = 0;
- parse->priv->discont = TRUE;
- }
-
- if (G_UNLIKELY (parse->priv->first_buffer)) {
- parse->priv->first_buffer = FALSE;
- if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) {
- /* this stream has no header buffers, check if we just prepend the
- * streamheader from caps to the stream */
- GST_DEBUG_OBJECT (parse, "Looking for streamheader field on caps to "
- "prepend to the stream");
- gst_base_parse_process_streamheader (parse);
- } else {
- GST_DEBUG_OBJECT (parse, "Stream has header buffers, not prepending "
- "streamheader from caps");
- }
- }
-
- if (parse->priv->detecting) {
- GstBuffer *detect_buf;
-
- if (parse->priv->detect_buffers_size == 0) {
- detect_buf = gst_buffer_ref (buffer);
- } else {
- GList *l;
- guint offset = 0;
-
- detect_buf = gst_buffer_new ();
-
- for (l = parse->priv->detect_buffers; l; l = l->next) {
- gsize tmpsize = gst_buffer_get_size (l->data);
-
- gst_buffer_copy_into (detect_buf, GST_BUFFER_CAST (l->data),
- GST_BUFFER_COPY_MEMORY, offset, tmpsize);
- offset += tmpsize;
- }
- if (buffer)
- gst_buffer_copy_into (detect_buf, buffer, GST_BUFFER_COPY_MEMORY,
- offset, gst_buffer_get_size (buffer));
- }
-
- ret = bclass->detect (parse, detect_buf);
- gst_buffer_unref (detect_buf);
-
- if (ret == GST_FLOW_OK) {
- GList *l;
-
- /* Detected something */
- parse->priv->detecting = FALSE;
-
- for (l = parse->priv->detect_buffers; l; l = l->next) {
- if (ret == GST_FLOW_OK && !parse->priv->flushing)
- ret =
- gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
- parent, GST_BUFFER_CAST (l->data));
- else
- gst_buffer_unref (GST_BUFFER_CAST (l->data));
- }
- g_list_free (parse->priv->detect_buffers);
- parse->priv->detect_buffers = NULL;
- parse->priv->detect_buffers_size = 0;
-
- if (ret != GST_FLOW_OK) {
- return ret;
- }
-
- /* Handle the current buffer */
- } else if (ret == GST_FLOW_NOT_NEGOTIATED) {
- /* Still detecting, append buffer or error out if draining */
-
- if (parse->priv->drain) {
- GST_DEBUG_OBJECT (parse, "Draining but did not detect format yet");
- return GST_FLOW_ERROR;
- } else if (parse->priv->flushing) {
- g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref,
- NULL);
- g_list_free (parse->priv->detect_buffers);
- parse->priv->detect_buffers = NULL;
- parse->priv->detect_buffers_size = 0;
- } else {
- parse->priv->detect_buffers =
- g_list_append (parse->priv->detect_buffers, buffer);
- parse->priv->detect_buffers_size += gst_buffer_get_size (buffer);
- return GST_FLOW_OK;
- }
- } else {
- /* Something went wrong, subclass responsible for error reporting */
- return ret;
- }
-
- /* And now handle the current buffer if detection worked */
- }
-
- if (G_LIKELY (buffer)) {
- GST_LOG_OBJECT (parse,
- "buffer size: %" G_GSIZE_FORMAT ", offset = %" G_GINT64_FORMAT
- ", dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT,
- gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer),
- GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
- GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
-
- if (G_UNLIKELY (!parse->priv->disable_passthrough
- && parse->priv->passthrough)) {
- GstBaseParseFrame frame;
-
- gst_base_parse_frame_init (&frame);
- frame.buffer = gst_buffer_make_writable (buffer);
- ret = gst_base_parse_push_frame (parse, &frame);
- gst_base_parse_frame_free (&frame);
- return ret;
- }
- if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
- /* upstream feeding us in reverse playback;
- * finish previous fragment and start new upon DISCONT */
- if (parse->segment.rate < 0.0) {
- GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment");
- ret = gst_base_parse_finish_fragment (parse, TRUE);
- gst_base_parse_start_fragment (parse);
- } else {
- /* discont in the stream, drain and mark discont for next output */
- gst_base_parse_drain (parse);
- parse->priv->discont = TRUE;
- }
- }
- gst_adapter_push (parse->priv->adapter, buffer);
- }
-
- /* Parse and push as many frames as possible */
- /* Stop either when adapter is empty or we are flushing */
- while (!parse->priv->flushing) {
- gint flush = 0;
- gboolean updated_prev_pts = FALSE;
-
- /* note: if subclass indicates MAX fsize,
- * this will not likely be available anyway ... */
- min_size = MAX (parse->priv->min_frame_size, fsize);
- av = gst_adapter_available (parse->priv->adapter);
-
- if (G_UNLIKELY (parse->priv->drain)) {
- min_size = av;
- GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size);
- if (G_UNLIKELY (!min_size)) {
- goto done;
- }
- }
-
- /* Collect at least min_frame_size bytes */
- if (av < min_size) {
- GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", av);
- goto done;
- }
-
- /* move along with upstream timestamp (if any),
- * but interpolate in between */
- pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
- dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
- if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) {
- parse->priv->prev_pts = parse->priv->next_pts = pts;
- updated_prev_pts = TRUE;
- }
-
- if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) {
- parse->priv->prev_dts = parse->priv->next_dts = dts;
- parse->priv->prev_dts_from_pts = FALSE;
- }
-
- /* we can mess with, erm interpolate, timestamps,
- * and incoming stuff has PTS but no DTS seen so far,
- * then pick up DTS from PTS and hope for the best ... */
- if (parse->priv->infer_ts &&
- parse->priv->pts_interpolate &&
- !GST_CLOCK_TIME_IS_VALID (dts) &&
- (!GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts)
- || (parse->priv->prev_dts_from_pts && updated_prev_pts))
- && GST_CLOCK_TIME_IS_VALID (pts)) {
- parse->priv->prev_dts = parse->priv->next_dts = pts;
- parse->priv->prev_dts_from_pts = TRUE;
- }
-
- /* always pass all available data */
- tmpbuf = gst_adapter_get_buffer (parse->priv->adapter, av);
-
- /* already inform subclass what timestamps we have planned,
- * at least if provided by time-based upstream */
- if (parse->priv->upstream_format == GST_FORMAT_TIME) {
- tmpbuf = gst_buffer_make_writable (tmpbuf);
- GST_BUFFER_PTS (tmpbuf) = parse->priv->next_pts;
- GST_BUFFER_DTS (tmpbuf) = parse->priv->next_dts;
- GST_BUFFER_DURATION (tmpbuf) = GST_CLOCK_TIME_NONE;
- }
-
- /* keep the adapter mapped, so keep track of what has to be flushed */
- ret = gst_base_parse_handle_buffer (parse, tmpbuf, &skip, &flush);
- tmpbuf = NULL;
-
- if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
- goto done;
- }
- if (skip == 0 && flush == 0) {
- GST_LOG_OBJECT (parse, "nothing skipped and no frames finished, "
- "breaking to get more data");
- /* ignore this return as it produced no data */
- ret = old_ret;
- goto done;
- }
- if (old_ret == GST_FLOW_OK)
- old_ret = ret;
- }
-
-done:
- GST_LOG_OBJECT (parse, "chain leaving");
- return ret;
-}
-
-/* Return the number of bytes available in the cached
- * read buffer, if any */
-static guint
-gst_base_parse_get_cached_available (GstBaseParse * parse)
-{
- if (parse->priv->cache != NULL) {
- gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
- gint cache_size = gst_buffer_get_size (parse->priv->cache);
-
- if (parse->priv->offset >= cache_offset
- && parse->priv->offset < cache_offset + cache_size)
- return cache_size - (parse->priv->offset - cache_offset); /* Size of the cache minus consumed */
- }
- return 0;
-}
-
-/* pull @size bytes at current offset,
- * i.e. at least try to and possibly return a shorter buffer if near the end */
-static GstFlowReturn
-gst_base_parse_pull_range (GstBaseParse * parse, guint size,
- GstBuffer ** buffer)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- guint read_size;
-
- g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
-
- /* Caching here actually makes much less difference than one would expect.
- * We do it mainly to avoid pulling buffers of 1 byte all the time */
- if (parse->priv->cache) {
- gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
- gint cache_size = gst_buffer_get_size (parse->priv->cache);
-
- if (cache_offset <= parse->priv->offset &&
- (parse->priv->offset + size) <= (cache_offset + cache_size)) {
- *buffer = gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL,
- parse->priv->offset - cache_offset, size);
- GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
- GST_LOG_OBJECT (parse,
- "Satisfying read request of %u bytes from cached buffer with offset %"
- G_GINT64_FORMAT, size, cache_offset);
- return GST_FLOW_OK;
- }
- /* not enough data in the cache, free cache and get a new one */
- gst_buffer_unref (parse->priv->cache);
- parse->priv->cache = NULL;
- }
-
- /* refill the cache */
- read_size = MAX (64 * 1024, size);
- GST_LOG_OBJECT (parse,
- "Reading cache buffer of %u bytes from offset %" G_GINT64_FORMAT,
- read_size, parse->priv->offset);
- ret =
- gst_pad_pull_range (parse->sinkpad, parse->priv->offset, read_size,
- &parse->priv->cache);
- if (ret != GST_FLOW_OK) {
- parse->priv->cache = NULL;
- return ret;
- }
-
- if (gst_buffer_get_size (parse->priv->cache) < size) {
- GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %"
- G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
- parse->priv->offset, size, gst_buffer_get_size (parse->priv->cache));
-
- *buffer = parse->priv->cache;
- parse->priv->cache = NULL;
-
- return GST_FLOW_OK;
- }
-
- GST_BUFFER_OFFSET (parse->priv->cache) = parse->priv->offset;
-
- *buffer =
- gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, size);
- GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_base_parse_handle_previous_fragment (GstBaseParse * parse)
-{
- gint64 offset = 0;
- GstClockTime ts = 0;
- GstBuffer *buffer;
- GstFlowReturn ret;
-
- GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT
- ", last_offset = %" G_GINT64_FORMAT,
- GST_TIME_ARGS (parse->priv->last_pts), parse->priv->last_offset);
-
- if (!parse->priv->last_offset
- || parse->priv->last_pts <= parse->segment.start) {
- GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT,
- GST_TIME_ARGS (parse->segment.start));
- ret = GST_FLOW_EOS;
- goto exit;
- }
-
- /* last fragment started at last_offset / last_ts;
- * seek back 10s capped at 1MB */
- if (parse->priv->last_pts >= 10 * GST_SECOND)
- ts = parse->priv->last_pts - 10 * GST_SECOND;
- /* if we are exact now, we will be more so going backwards */
- if (parse->priv->exact_position) {
- offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL);
- } else {
- if (!gst_base_parse_convert (parse, GST_FORMAT_TIME, ts,
- GST_FORMAT_BYTES, &offset)) {
- GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based");
- }
- }
- offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024,
- parse->priv->last_offset - 1024);
- offset = MAX (0, offset);
-
- GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT,
- offset);
- parse->priv->offset = offset;
-
- ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset,
- &buffer);
- if (ret != GST_FLOW_OK)
- goto exit;
-
- /* offset will increase again as fragment is processed/parsed */
- parse->priv->last_offset = offset;
-
- gst_base_parse_start_fragment (parse);
- gst_adapter_push (parse->priv->adapter, buffer);
- ret = gst_base_parse_finish_fragment (parse, TRUE);
- if (ret != GST_FLOW_OK)
- goto exit;
-
- /* force previous fragment */
- parse->priv->offset = -1;
-
-exit:
- return ret;
-}
-
-/* PULL mode:
- * pull and scan for next frame starting from current offset
- * adjusts sync, drain and offset going along */
-static GstFlowReturn
-gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
-{
- GstBuffer *buffer;
- GstFlowReturn ret = GST_FLOW_OK;
- guint fsize, min_size;
- gint flushed = 0;
- gint skip = 0;
-
- GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
- " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
-
- /* let's make this efficient for all subclass once and for all;
- * maybe it does not need this much, but in the latter case, we know we are
- * in pull mode here and might as well try to read and supply more anyway,
- * so start with the cached buffer, or if that's shrunk below 1024 bytes,
- * pull a new cache buffer */
- fsize = gst_base_parse_get_cached_available (parse);
- if (fsize < 1024)
- fsize = 64 * 1024;
-
- while (TRUE) {
- min_size = MAX (parse->priv->min_frame_size, fsize);
-
- GST_LOG_OBJECT (parse, "reading buffer size %u", min_size);
-
- parse->priv->drain = FALSE;
- ret = gst_base_parse_pull_range (parse, min_size, &buffer);
- if (ret != GST_FLOW_OK)
- goto done;
-
- /* if we got a short read, inform subclass we are draining leftover
- * and no more is to be expected */
- if (gst_buffer_get_size (buffer) < min_size) {
- GST_LOG_OBJECT (parse, "... but did not get that; marked draining");
- parse->priv->drain = TRUE;
- }
-
- if (parse->priv->detecting) {
- ret = klass->detect (parse, buffer);
- if (ret == GST_FLOW_NOT_NEGOTIATED) {
- /* If draining we error out, otherwise request a buffer
- * with 64kb more */
- if (parse->priv->drain) {
- gst_buffer_unref (buffer);
- GST_ERROR_OBJECT (parse, "Failed to detect format but draining");
- return GST_FLOW_ERROR;
- } else {
- /* Double our frame size, or increment by at most 64KB */
- fsize += MIN (fsize, 64 * 1024);
- gst_buffer_unref (buffer);
- continue;
- }
- } else if (ret != GST_FLOW_OK) {
- gst_buffer_unref (buffer);
- GST_ERROR_OBJECT (parse, "detect() returned %s",
- gst_flow_get_name (ret));
- return ret;
- }
-
- /* Else handle this buffer normally */
- }
-
- ret = gst_base_parse_handle_buffer (parse, buffer, &skip, &flushed);
- if (ret != GST_FLOW_OK)
- break;
-
- /* If a large amount of data was requested to be skipped, _handle_buffer
- might have set the priv->skip flag to an extra amount on top of skip.
- In pull mode, we can just pull from the new offset directly. */
- parse->priv->offset += parse->priv->skip;
- parse->priv->skip = 0;
-
- /* something flushed means something happened,
- * and we should bail out of this loop so as not to occupy
- * the task thread indefinitely */
- if (flushed) {
- GST_LOG_OBJECT (parse, "frame finished, breaking loop");
- break;
- }
- if (!skip) {
- if (parse->priv->drain) {
- /* nothing flushed, no skip and draining, so nothing left to do */
- GST_LOG_OBJECT (parse, "no activity or result when draining; "
- "breaking loop and marking EOS");
- ret = GST_FLOW_EOS;
- break;
- }
- /* otherwise, get some more data
- * note that is checked this does not happen indefinitely */
- GST_LOG_OBJECT (parse, "getting some more data");
-
- /* Double our frame size, or increment by at most 64KB */
- fsize += MIN (fsize, 64 * 1024);
- }
- }
-
-done:
- return ret;
-}
-
-/* Loop that is used in pull mode to retrieve data from upstream */
-static void
-gst_base_parse_loop (GstPad * pad)
-{
- GstBaseParse *parse;
- GstBaseParseClass *klass;
- GstFlowReturn ret = GST_FLOW_OK;
-
- parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
- klass = GST_BASE_PARSE_GET_CLASS (parse);
-
- GST_LOG_OBJECT (parse, "Entering parse loop");
-
- if (G_UNLIKELY (parse->priv->push_stream_start)) {
- gchar *stream_id;
- GstEvent *event;
-
- stream_id =
- gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (parse),
- NULL);
-
- event = gst_event_new_stream_start (stream_id);
- gst_event_set_group_id (event, gst_util_group_id_next ());
-
- GST_DEBUG_OBJECT (parse, "Pushing STREAM_START");
- gst_pad_push_event (parse->srcpad, event);
- parse->priv->push_stream_start = FALSE;
- g_free (stream_id);
- }
-
- /* reverse playback:
- * first fragment (closest to stop time) is handled normally below,
- * then we pull in fragments going backwards */
- if (parse->segment.rate < 0.0) {
- /* check if we jumped back to a previous fragment,
- * which is a post-first fragment */
- if (parse->priv->offset < 0) {
- ret = gst_base_parse_handle_previous_fragment (parse);
- goto done;
- }
- }
-
- ret = gst_base_parse_scan_frame (parse, klass);
-
- /* eat expected eos signalling past segment in reverse playback */
- if (parse->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
- parse->segment.position >= parse->segment.stop) {
- GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
- /* push what was accumulated during loop run */
- gst_base_parse_finish_fragment (parse, FALSE);
- /* force previous fragment */
- parse->priv->offset = -1;
- goto eos;
- }
-
- if (ret != GST_FLOW_OK)
- goto done;
-
-done:
- if (ret == GST_FLOW_EOS)
- goto eos;
- else if (ret != GST_FLOW_OK)
- goto pause;
-
- gst_object_unref (parse);
- return;
-
- /* ERRORS */
-eos:
- {
- ret = GST_FLOW_EOS;
- GST_DEBUG_OBJECT (parse, "eos");
- /* fall-through */
- }
-pause:
- {
- gboolean push_eos = FALSE;
-
- GST_DEBUG_OBJECT (parse, "pausing task, reason %s",
- gst_flow_get_name (ret));
- gst_pad_pause_task (parse->sinkpad);
-
- if (ret == GST_FLOW_EOS) {
- /* handle end-of-stream/segment */
- if (parse->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
- gint64 stop;
-
- if ((stop = parse->segment.stop) == -1)
- stop = parse->segment.duration;
-
- GST_DEBUG_OBJECT (parse, "sending segment_done");
-
- gst_element_post_message
- (GST_ELEMENT_CAST (parse),
- gst_message_new_segment_done (GST_OBJECT_CAST (parse),
- GST_FORMAT_TIME, stop));
- gst_pad_push_event (parse->srcpad,
- gst_event_new_segment_done (GST_FORMAT_TIME, stop));
- } else {
- /* If we STILL have zero frames processed, fire an error */
- if (parse->priv->framecount == 0) {
- GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
- ("No valid frames found before end of stream"), (NULL));
- }
- push_eos = TRUE;
- }
- } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
- /* for fatal errors we post an error message, wrong-state is
- * not fatal because it happens due to flushes and only means
- * that we should stop now. */
- GST_ELEMENT_FLOW_ERROR (parse, ret);
- push_eos = TRUE;
- }
- if (push_eos) {
- GstEvent *topush;
- if (parse->priv->estimated_duration <= 0) {
- gst_base_parse_update_duration (parse);
- }
- /* Push pending events, including SEGMENT events */
- gst_base_parse_push_pending_events (parse);
-
- topush = gst_event_new_eos ();
- GST_DEBUG_OBJECT (parse, "segment_seqnum:%" G_GUINT32_FORMAT,
- parse->priv->segment_seqnum);
- if (parse->priv->segment_seqnum != GST_SEQNUM_INVALID)
- gst_event_set_seqnum (topush, parse->priv->segment_seqnum);
- gst_pad_push_event (parse->srcpad, topush);
- }
- gst_object_unref (parse);
- }
-}
-
-static gboolean
-gst_base_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
-{
- GstSchedulingFlags sched_flags;
- GstBaseParse *parse;
- GstQuery *query;
- gboolean pull_mode;
-
- parse = GST_BASE_PARSE (parent);
-
- GST_DEBUG_OBJECT (parse, "sink activate");
-
- query = gst_query_new_scheduling ();
- if (!gst_pad_peer_query (sinkpad, query)) {
- gst_query_unref (query);
- goto baseparse_push;
- }
-
- gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
-
- pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL)
- && ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0);
-
- gst_query_unref (query);
-
- if (!pull_mode)
- goto baseparse_push;
-
- GST_DEBUG_OBJECT (parse, "trying to activate in pull mode");
- if (!gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE))
- goto baseparse_push;
-
- parse->priv->push_stream_start = TRUE;
- /* In pull mode, upstream is BYTES */
- parse->priv->upstream_format = GST_FORMAT_BYTES;
-
- return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_base_parse_loop,
- sinkpad, NULL);
- /* fallback */
-baseparse_push:
- {
- GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
- return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
- }
-}
-
-static gboolean
-gst_base_parse_activate (GstBaseParse * parse, gboolean active)
-{
- GstBaseParseClass *klass;
- gboolean result = TRUE;
-
- GST_DEBUG_OBJECT (parse, "activate %d", active);
-
- klass = GST_BASE_PARSE_GET_CLASS (parse);
-
- if (active) {
- if (parse->priv->pad_mode == GST_PAD_MODE_NONE && klass->start)
- result = klass->start (parse);
-
- /* If the subclass implements ::detect we want to
- * call it for the first buffers now */
- parse->priv->detecting = (klass->detect != NULL);
- } else {
- /* We must make sure streaming has finished before resetting things
- * and calling the ::stop vfunc */
- GST_PAD_STREAM_LOCK (parse->sinkpad);
- GST_PAD_STREAM_UNLOCK (parse->sinkpad);
-
- if (parse->priv->pad_mode != GST_PAD_MODE_NONE && klass->stop)
- result = klass->stop (parse);
-
- parse->priv->pad_mode = GST_PAD_MODE_NONE;
- parse->priv->upstream_format = GST_FORMAT_UNDEFINED;
- }
- GST_DEBUG_OBJECT (parse, "activate return: %d", result);
- return result;
-}
-
-static gboolean
-gst_base_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active)
-{
- gboolean result;
- GstBaseParse *parse;
-
- parse = GST_BASE_PARSE (parent);
-
- GST_DEBUG_OBJECT (parse, "sink %sactivate in %s mode",
- (active) ? "" : "de", gst_pad_mode_get_name (mode));
-
- if (!gst_base_parse_activate (parse, active))
- goto activate_failed;
-
- switch (mode) {
- case GST_PAD_MODE_PULL:
- if (active) {
- GstEvent *ev = gst_event_new_segment (&parse->segment);
-
- if (parse->priv->segment_seqnum != GST_SEQNUM_INVALID)
- gst_event_set_seqnum (ev, parse->priv->segment_seqnum);
- else
- parse->priv->segment_seqnum = gst_event_get_seqnum (ev);
-
- parse->priv->pending_events =
- g_list_prepend (parse->priv->pending_events, ev);
- result = TRUE;
- } else {
- result = gst_pad_stop_task (pad);
- }
- break;
- default:
- result = TRUE;
- break;
- }
- if (result)
- parse->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
-
- GST_DEBUG_OBJECT (parse, "sink activate return: %d", result);
-
- return result;
-
- /* ERRORS */
-activate_failed:
- {
- GST_DEBUG_OBJECT (parse, "activate failed");
- return FALSE;
- }
-}
-
-/**
- * gst_base_parse_set_duration:
- * @parse: #GstBaseParse.
- * @fmt: #GstFormat.
- * @duration: duration value.
- * @interval: how often to update the duration estimate based on bitrate, or 0.
- *
- * Sets the duration of the currently playing media. Subclass can use this
- * when it is able to determine duration and/or notices a change in the media
- * duration. Alternatively, if @interval is non-zero (default), then stream
- * duration is determined based on estimated bitrate, and updated every @interval
- * frames.
- */
-void
-gst_base_parse_set_duration (GstBaseParse * parse,
- GstFormat fmt, gint64 duration, gint interval)
-{
- gint64 old_duration;
-
- g_return_if_fail (parse != NULL);
-
- if (parse->priv->upstream_has_duration) {
- GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update");
- goto exit;
- }
-
- old_duration = parse->priv->duration;
-
- parse->priv->duration = duration;
- parse->priv->duration_fmt = fmt;
- GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration);
- if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) {
- if (interval != 0) {
- GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate");
- interval = 0;
- }
- }
- GST_DEBUG_OBJECT (parse, "set update interval: %d", interval);
- parse->priv->update_interval = interval;
- if (duration != old_duration) {
- GstMessage *m;
-
- m = gst_message_new_duration_changed (GST_OBJECT (parse));
- gst_element_post_message (GST_ELEMENT (parse), m);
-
- /* TODO: what about duration tag? */
- }
-exit:
- return;
-}
-
-/**
- * gst_base_parse_set_average_bitrate:
- * @parse: #GstBaseParse.
- * @bitrate: average bitrate in bits/second
- *
- * Optionally sets the average bitrate detected in media (if non-zero),
- * e.g. based on metadata, as it will be posted to the application.
- *
- * By default, announced average bitrate is estimated. The average bitrate
- * is used to estimate the total duration of the stream and to estimate
- * a seek position, if there's no index and the format is syncable
- * (see gst_base_parse_set_syncable()).
- */
-void
-gst_base_parse_set_average_bitrate (GstBaseParse * parse, guint bitrate)
-{
- parse->priv->bitrate = bitrate;
- GST_DEBUG_OBJECT (parse, "bitrate %u", bitrate);
-}
-
-/**
- * gst_base_parse_set_min_frame_size:
- * @parse: #GstBaseParse.
- * @min_size: Minimum size in bytes of the data that this base class should
- * give to subclass.
- *
- * Subclass can use this function to tell the base class that it needs to
- * be given buffers of at least @min_size bytes.
- */
-void
-gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size)
-{
- g_return_if_fail (parse != NULL);
-
- parse->priv->min_frame_size = min_size;
- GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size);
-}
-
-/**
- * gst_base_parse_set_frame_rate:
- * @parse: the #GstBaseParse to set
- * @fps_num: frames per second (numerator).
- * @fps_den: frames per second (denominator).
- * @lead_in: frames needed before a segment for subsequent decode
- * @lead_out: frames needed after a segment
- *
- * If frames per second is configured, parser can take care of buffer duration
- * and timestamping. When performing segment clipping, or seeking to a specific
- * location, a corresponding decoder might need an initial @lead_in and a
- * following @lead_out number of frames to ensure the desired segment is
- * entirely filled upon decoding.
- */
-void
-gst_base_parse_set_frame_rate (GstBaseParse * parse, guint fps_num,
- guint fps_den, guint lead_in, guint lead_out)
-{
- g_return_if_fail (parse != NULL);
-
- parse->priv->fps_num = fps_num;
- parse->priv->fps_den = fps_den;
- if (!fps_num || !fps_den) {
- GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters",
- fps_num, fps_den);
- fps_num = fps_den = 0;
- parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
- parse->priv->lead_in = parse->priv->lead_out = 0;
- parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
- } else {
- parse->priv->frame_duration =
- gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
- parse->priv->lead_in = lead_in;
- parse->priv->lead_out = lead_out;
- parse->priv->lead_in_ts =
- gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num);
- parse->priv->lead_out_ts =
- gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
- /* aim for about 1.5s to estimate duration */
- if (parse->priv->update_interval < 0) {
- guint64 interval = gst_util_uint64_scale (fps_num, 3,
- G_GUINT64_CONSTANT (2) * fps_den);
-
- parse->priv->update_interval = MIN (interval, G_MAXINT);
-
- GST_LOG_OBJECT (parse, "estimated update interval to %d frames",
- parse->priv->update_interval);
- }
- }
- GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
- fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
- GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, "
- "lead out: %d frames = %" G_GUINT64_FORMAT " ms",
- lead_in, parse->priv->lead_in_ts / GST_MSECOND,
- lead_out, parse->priv->lead_out_ts / GST_MSECOND);
-}
-
-/**
- * gst_base_parse_set_has_timing_info:
- * @parse: a #GstBaseParse
- * @has_timing: whether frames carry timing information
- *
- * Set if frames carry timing information which the subclass can (generally)
- * parse and provide. In particular, intrinsic (rather than estimated) time
- * can be obtained following a seek.
- */
-void
-gst_base_parse_set_has_timing_info (GstBaseParse * parse, gboolean has_timing)
-{
- parse->priv->has_timing_info = has_timing;
- GST_INFO_OBJECT (parse, "has_timing: %s", (has_timing) ? "yes" : "no");
-}
-
-/**
- * gst_base_parse_set_syncable:
- * @parse: a #GstBaseParse
- * @syncable: set if frame starts can be identified
- *
- * Set if frame starts can be identified. This is set by default and
- * determines whether seeking based on bitrate averages
- * is possible for a format/stream.
- */
-void
-gst_base_parse_set_syncable (GstBaseParse * parse, gboolean syncable)
-{
- parse->priv->syncable = syncable;
- GST_INFO_OBJECT (parse, "syncable: %s", (syncable) ? "yes" : "no");
-}
-
-/**
- * gst_base_parse_set_passthrough:
- * @parse: a #GstBaseParse
- * @passthrough: %TRUE if parser should run in passthrough mode
- *
- * Set if the nature of the format or configuration does not allow (much)
- * parsing, and the parser should operate in passthrough mode (which only
- * applies when operating in push mode). That is, incoming buffers are
- * pushed through unmodified, i.e. no #GstBaseParseClass::handle_frame
- * will be invoked, but #GstBaseParseClass::pre_push_frame will still be
- * invoked, so subclass can perform as much or as little is appropriate for
- * passthrough semantics in #GstBaseParseClass::pre_push_frame.
- */
-void
-gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
-{
- parse->priv->passthrough = passthrough;
- GST_INFO_OBJECT (parse, "passthrough: %s", (passthrough) ? "yes" : "no");
-}
-
-/**
- * gst_base_parse_set_pts_interpolation:
- * @parse: a #GstBaseParse
- * @pts_interpolate: %TRUE if parser should interpolate PTS timestamps
- *
- * By default, the base class will guess PTS timestamps using a simple
- * interpolation (previous timestamp + duration), which is incorrect for
- * data streams with reordering, where PTS can go backward. Sub-classes
- * implementing such formats should disable PTS interpolation.
- */
-void
-gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
- gboolean pts_interpolate)
-{
- parse->priv->pts_interpolate = pts_interpolate;
- GST_INFO_OBJECT (parse, "PTS interpolation: %s",
- (pts_interpolate) ? "yes" : "no");
-}
-
-/**
- * gst_base_parse_set_infer_ts:
- * @parse: a #GstBaseParse
- * @infer_ts: %TRUE if parser should infer DTS/PTS from each other
- *
- * By default, the base class might try to infer PTS from DTS and vice
- * versa. While this is generally correct for audio data, it may not
- * be otherwise. Sub-classes implementing such formats should disable
- * timestamp inferring.
- */
-void
-gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts)
-{
- parse->priv->infer_ts = infer_ts;
- GST_INFO_OBJECT (parse, "TS inferring: %s", (infer_ts) ? "yes" : "no");
-}
-
-/**
- * gst_base_parse_set_latency:
- * @parse: a #GstBaseParse
- * @min_latency: minimum parse latency
- * @max_latency: maximum parse latency
- *
- * Sets the minimum and maximum (which may likely be equal) latency introduced
- * by the parsing process. If there is such a latency, which depends on the
- * particular parsing of the format, it typically corresponds to 1 frame duration.
- */
-void
-gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
- GstClockTime max_latency)
-{
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
- g_return_if_fail (min_latency <= max_latency);
-
- GST_OBJECT_LOCK (parse);
- parse->priv->min_latency = min_latency;
- parse->priv->max_latency = max_latency;
- GST_OBJECT_UNLOCK (parse);
- GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %"
- GST_TIME_FORMAT, GST_TIME_ARGS (min_latency),
- GST_TIME_ARGS (max_latency));
-}
-
-static gboolean
-gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
- GstClockTime * duration)
-{
- gboolean res = FALSE;
-
- g_return_val_if_fail (duration != NULL, FALSE);
-
- *duration = GST_CLOCK_TIME_NONE;
- if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) {
- GST_LOG_OBJECT (parse, "using provided duration");
- *duration = parse->priv->duration;
- res = TRUE;
- } else if (parse->priv->duration != -1) {
- GST_LOG_OBJECT (parse, "converting provided duration");
- res = gst_base_parse_convert (parse, parse->priv->duration_fmt,
- parse->priv->duration, format, (gint64 *) duration);
- } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) {
- GST_LOG_OBJECT (parse, "using estimated duration");
- *duration = parse->priv->estimated_duration;
- res = TRUE;
- } else {
- GST_LOG_OBJECT (parse, "cannot estimate duration");
- }
-
- GST_LOG_OBJECT (parse, "res: %d, duration %" GST_TIME_FORMAT, res,
- GST_TIME_ARGS (*duration));
- return res;
-}
-
-static gboolean
-gst_base_parse_src_query_default (GstBaseParse * parse, GstQuery * query)
-{
- gboolean res = FALSE;
- GstPad *pad;
-
- pad = GST_BASE_PARSE_SRC_PAD (parse);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 dest_value;
- GstFormat format;
-
- GST_DEBUG_OBJECT (parse, "position query");
- gst_query_parse_position (query, &format, NULL);
-
- /* try upstream first */
- res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
- if (!res) {
- /* Fall back on interpreting segment */
- GST_OBJECT_LOCK (parse);
- /* Only reply BYTES if upstream is in BYTES already, otherwise
- * we're not in charge */
- if (format == GST_FORMAT_BYTES
- && parse->priv->upstream_format == GST_FORMAT_BYTES) {
- dest_value = parse->priv->offset;
- res = TRUE;
- } else if (format == parse->segment.format &&
- GST_CLOCK_TIME_IS_VALID (parse->segment.position)) {
- dest_value = gst_segment_to_stream_time (&parse->segment,
- parse->segment.format, parse->segment.position);
- res = TRUE;
- }
- GST_OBJECT_UNLOCK (parse);
- if (!res && parse->priv->upstream_format == GST_FORMAT_BYTES) {
- /* no precise result, upstream no idea either, then best estimate */
- /* priv->offset is updated in both PUSH/PULL modes, *iff* we're
- * in charge of things */
- res = gst_base_parse_convert (parse,
- GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value);
- }
- if (res)
- gst_query_set_position (query, format, dest_value);
- }
- break;
- }
- case GST_QUERY_DURATION:
- {
- GstFormat format;
- GstClockTime duration;
-
- GST_DEBUG_OBJECT (parse, "duration query");
- gst_query_parse_duration (query, &format, NULL);
-
- /* consult upstream */
- res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
-
- /* otherwise best estimate from us */
- if (!res) {
- res = gst_base_parse_get_duration (parse, format, &duration);
- if (res)
- gst_query_set_duration (query, format, duration);
- }
- break;
- }
- case GST_QUERY_SEEKING:
- {
- GstFormat fmt;
- GstClockTime duration = GST_CLOCK_TIME_NONE;
- gboolean seekable = FALSE;
-
- GST_DEBUG_OBJECT (parse, "seeking query");
- gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
-
- /* consult upstream */
- res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
-
- /* we may be able to help if in TIME */
- if (fmt == GST_FORMAT_TIME && gst_base_parse_is_seekable (parse)) {
- gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
- /* already OK if upstream takes care */
- GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d",
- res, seekable);
- if (!(res && seekable)) {
- if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration)
- || duration == -1) {
- /* seekable if we still have a chance to get duration later on */
- seekable = parse->priv->upstream_seekable &&
- (parse->priv->update_interval > 0);
- } else {
- seekable = parse->priv->upstream_seekable;
- GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d",
- seekable);
- }
- gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
- res = TRUE;
- }
- }
- break;
- }
- case GST_QUERY_FORMATS:
- gst_query_set_formatsv (query, 3, fmtlist);
- res = TRUE;
- break;
- case GST_QUERY_CONVERT:
- {
- GstFormat src_format, dest_format;
- gint64 src_value, dest_value;
-
- gst_query_parse_convert (query, &src_format, &src_value,
- &dest_format, &dest_value);
-
- res = gst_base_parse_convert (parse, src_format, src_value,
- dest_format, &dest_value);
- if (res) {
- gst_query_set_convert (query, src_format, src_value,
- dest_format, dest_value);
- }
- break;
- }
- case GST_QUERY_LATENCY:
- {
- if ((res = gst_pad_peer_query (parse->sinkpad, query))) {
- gboolean live;
- GstClockTime min_latency, max_latency;
-
- gst_query_parse_latency (query, &live, &min_latency, &max_latency);
- GST_DEBUG_OBJECT (parse, "Peer latency: live %d, min %"
- GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
- GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
- GST_OBJECT_LOCK (parse);
- /* add our latency */
- min_latency += parse->priv->min_latency;
- if (max_latency == -1 || parse->priv->max_latency == -1)
- max_latency = -1;
- else
- max_latency += parse->priv->max_latency;
- GST_OBJECT_UNLOCK (parse);
-
- gst_query_set_latency (query, live, min_latency, max_latency);
- }
- break;
- }
- case GST_QUERY_SEGMENT:
- {
- GstFormat format;
- gint64 start, stop;
-
- format = parse->segment.format;
-
- start =
- gst_segment_to_stream_time (&parse->segment, format,
- parse->segment.start);
- if ((stop = parse->segment.stop) == -1)
- stop = parse->segment.duration;
- else
- stop = gst_segment_to_stream_time (&parse->segment, format, stop);
-
- gst_query_set_segment (query, parse->segment.rate, format, start, stop);
- res = TRUE;
- break;
- }
- default:
- res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
- break;
- }
- return res;
-}
-
-/* scans for a cluster start from @pos,
- * return GST_FLOW_OK and frame position/time in @pos/@time if found */
-static GstFlowReturn
-gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
- GstClockTime * time, GstClockTime * duration)
-{
- GstBaseParseClass *klass;
- gint64 orig_offset;
- gboolean orig_drain, orig_discont;
- GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *buf = NULL;
- GstBaseParseFrame *sframe = NULL;
-
- g_return_val_if_fail (pos != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (time != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (duration != NULL, GST_FLOW_ERROR);
-
- klass = GST_BASE_PARSE_GET_CLASS (parse);
-
- *time = GST_CLOCK_TIME_NONE;
- *duration = GST_CLOCK_TIME_NONE;
-
- /* save state */
- orig_offset = parse->priv->offset;
- orig_discont = parse->priv->discont;
- orig_drain = parse->priv->drain;
-
- GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT
- " (%#" G_GINT64_MODIFIER "x)", *pos, *pos);
-
- /* jump elsewhere and locate next frame */
- parse->priv->offset = *pos;
- /* mark as scanning so frames don't get processed all the way */
- parse->priv->scanning = TRUE;
- ret = gst_base_parse_scan_frame (parse, klass);
- parse->priv->scanning = FALSE;
- /* retrieve frame found during scan */
- sframe = parse->priv->scanned_frame;
- parse->priv->scanned_frame = NULL;
-
- if (ret != GST_FLOW_OK || !sframe)
- goto done;
-
- /* get offset first, subclass parsing might dump other stuff in there */
- *pos = sframe->offset;
- buf = sframe->buffer;
- g_assert (buf);
-
- /* but it should provide proper time */
- *time = GST_BUFFER_TIMESTAMP (buf);
- *duration = GST_BUFFER_DURATION (buf);
-
- GST_LOG_OBJECT (parse,
- "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
- GST_TIME_ARGS (*time), *pos);
-
-done:
- if (sframe)
- gst_base_parse_frame_free (sframe);
-
- /* restore state */
- parse->priv->offset = orig_offset;
- parse->priv->discont = orig_discont;
- parse->priv->drain = orig_drain;
-
- return ret;
-}
-
-/* bisect and scan through file for frame starting before @time,
- * returns OK and @time/@offset if found, NONE and/or error otherwise
- * If @time == G_MAXINT64, scan for duration ( == last frame) */
-static GstFlowReturn
-gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time,
- gint64 * _offset)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- gint64 lpos, hpos, newpos;
- GstClockTime time, ltime, htime, newtime, dur;
- gboolean cont = TRUE;
- const GstClockTime tolerance = TARGET_DIFFERENCE;
- const guint chunk = 4 * 1024;
-
- g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR);
-
- GST_DEBUG_OBJECT (parse, "Bisecting for time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (*_time));
-
- /* TODO also make keyframe aware if useful some day */
-
- time = *_time;
-
- /* basic cases */
- if (time == 0) {
- *_offset = 0;
- return GST_FLOW_OK;
- }
-
- if (time == -1) {
- *_offset = -1;
- return GST_FLOW_OK;
- }
-
- /* do not know at first */
- *_offset = -1;
- *_time = GST_CLOCK_TIME_NONE;
-
- /* need initial positions; start and end */
- lpos = parse->priv->first_frame_offset;
- ltime = parse->priv->first_frame_pts;
- /* try other one if no luck */
- if (!GST_CLOCK_TIME_IS_VALID (ltime))
- ltime = parse->priv->first_frame_dts;
- if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &htime)) {
- GST_DEBUG_OBJECT (parse, "Unknown time duration, cannot bisect");
- return GST_FLOW_ERROR;
- }
- hpos = parse->priv->upstream_size;
-
- GST_DEBUG_OBJECT (parse,
- "Bisection initial bounds: bytes %" G_GINT64_FORMAT " %" G_GINT64_FORMAT
- ", times %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, lpos, hpos,
- GST_TIME_ARGS (ltime), GST_TIME_ARGS (htime));
-
- /* check preconditions are satisfied;
- * start and end are needed, except for special case where we scan for
- * last frame to determine duration */
- if (parse->priv->pad_mode != GST_PAD_MODE_PULL || !hpos ||
- !GST_CLOCK_TIME_IS_VALID (ltime) ||
- (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) {
- return GST_FLOW_OK;
- }
-
- /* shortcut cases */
- if (time < ltime) {
- goto exit;
- } else if (time < ltime + tolerance) {
- *_offset = lpos;
- *_time = ltime;
- goto exit;
- } else if (time >= htime) {
- *_offset = hpos;
- *_time = htime;
- goto exit;
- }
-
- while (htime > ltime && cont) {
- GST_LOG_OBJECT (parse,
- "lpos: %" G_GUINT64_FORMAT ", ltime: %" GST_TIME_FORMAT, lpos,
- GST_TIME_ARGS (ltime));
- GST_LOG_OBJECT (parse,
- "hpos: %" G_GUINT64_FORMAT ", htime: %" GST_TIME_FORMAT, hpos,
- GST_TIME_ARGS (htime));
- if (G_UNLIKELY (time == G_MAXINT64)) {
- newpos = hpos;
- } else if (G_LIKELY (hpos > lpos)) {
- newpos =
- gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) +
- lpos - chunk;
- } else {
- /* should mean lpos == hpos, since lpos <= hpos is invariant */
- newpos = lpos;
- /* we check this case once, but not forever, so break loop */
- cont = FALSE;
- }
-
- /* ensure */
- newpos = CLAMP (newpos, lpos, hpos);
- GST_LOG_OBJECT (parse,
- "estimated _offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT,
- GST_TIME_ARGS (time), newpos);
-
- ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur);
- if (ret == GST_FLOW_EOS) {
- /* heuristic HACK */
- hpos = MAX (lpos, hpos - chunk);
- continue;
- } else if (ret != GST_FLOW_OK) {
- goto exit;
- }
-
- if (newtime == -1 || newpos == -1) {
- GST_DEBUG_OBJECT (parse, "subclass did not provide metadata; aborting");
- break;
- }
-
- if (G_UNLIKELY (time == G_MAXINT64)) {
- *_offset = newpos;
- *_time = newtime;
- if (GST_CLOCK_TIME_IS_VALID (dur))
- *_time += dur;
- break;
- } else if (newtime > time) {
- /* overshoot */
- hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos);
- htime = newtime;
- } else if (newtime + tolerance > time) {
- /* close enough undershoot */
- *_offset = newpos;
- *_time = newtime;
- break;
- } else if (newtime < ltime) {
- /* so a position beyond lpos resulted in earlier time than ltime ... */
- GST_DEBUG_OBJECT (parse, "non-ascending time; aborting");
- break;
- } else {
- /* undershoot too far */
- newpos += newpos == lpos ? chunk : 0;
- lpos = CLAMP (newpos, lpos, hpos);
- ltime = newtime;
- }
- }
-
-exit:
- GST_LOG_OBJECT (parse, "return offset %" G_GINT64_FORMAT ", time %"
- GST_TIME_FORMAT, *_offset, GST_TIME_ARGS (*_time));
- return ret;
-}
-
-static gint64
-gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time,
- gboolean before, GstClockTime * _ts)
-{
- gint64 bytes = 0, ts = 0;
- GstIndexEntry *entry = NULL;
-
- if (time == GST_CLOCK_TIME_NONE) {
- ts = time;
- bytes = -1;
- goto exit;
- }
-
- GST_BASE_PARSE_INDEX_LOCK (parse);
- if (parse->priv->index) {
- /* Let's check if we have an index entry for that time */
- entry = gst_index_get_assoc_entry (parse->priv->index,
- parse->priv->index_id,
- before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER,
- GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
- }
-
- if (entry) {
- gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
- gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts);
-
- GST_DEBUG_OBJECT (parse, "found index entry for %" GST_TIME_FORMAT
- " at %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT,
- GST_TIME_ARGS (time), GST_TIME_ARGS (ts), bytes);
- } else {
- GST_DEBUG_OBJECT (parse, "no index entry found for %" GST_TIME_FORMAT,
- GST_TIME_ARGS (time));
- if (!before) {
- bytes = -1;
- ts = GST_CLOCK_TIME_NONE;
- }
- }
- GST_BASE_PARSE_INDEX_UNLOCK (parse);
-
-exit:
- if (_ts)
- *_ts = ts;
-
- return bytes;
-}
-
-/* returns TRUE if seek succeeded */
-static gboolean
-gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
-{
- gdouble rate;
- GstFormat format;
- GstSeekFlags flags;
- GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type;
- gboolean flush, update, res = TRUE, accurate;
- gint64 start, stop, seekpos, seekstop;
- GstSegment seeksegment = { 0, };
- GstClockTime start_ts;
- guint32 seqnum;
- GstEvent *segment_event;
-
- /* try upstream first, unless we're driving the streaming thread ourselves */
- if (parse->priv->pad_mode != GST_PAD_MODE_PULL) {
- res = gst_pad_push_event (parse->sinkpad, gst_event_ref (event));
- if (res)
- goto done;
- }
-
- gst_event_parse_seek (event, &rate, &format, &flags,
- &start_type, &start, &stop_type, &stop);
- seqnum = gst_event_get_seqnum (event);
- parse->priv->segment_seqnum = seqnum;
-
- GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, "
- "start type %d at %" GST_TIME_FORMAT ", end type %d at %"
- GST_TIME_FORMAT, gst_format_get_name (format), rate,
- start_type, GST_TIME_ARGS (start), stop_type, GST_TIME_ARGS (stop));
-
- /* we can only handle TIME, so check if subclass can convert
- * to TIME format if it's some other format (such as DEFAULT) */
- if (format != GST_FORMAT_TIME) {
- if (!gst_base_parse_convert (parse, format, start, GST_FORMAT_TIME, &start)
- || !gst_base_parse_convert (parse, format, stop, GST_FORMAT_TIME,
- &stop))
- goto no_convert_to_time;
-
- GST_INFO_OBJECT (parse, "converted %s format to start time "
- "%" GST_TIME_FORMAT " and stop time %" GST_TIME_FORMAT,
- gst_format_get_name (format), GST_TIME_ARGS (start),
- GST_TIME_ARGS (stop));
-
- format = GST_FORMAT_TIME;
- }
-
- /* no negative rates in push mode (unless upstream takes care of that, but
- * we've already tried upstream and it didn't handle the seek request) */
- if (rate < 0.0 && parse->priv->pad_mode == GST_PAD_MODE_PUSH)
- goto negative_rate;
-
- if (start_type != GST_SEEK_TYPE_SET ||
- (stop_type != GST_SEEK_TYPE_SET && stop_type != GST_SEEK_TYPE_NONE))
- goto wrong_type;
-
- /* get flush flag */
- flush = flags & GST_SEEK_FLAG_FLUSH;
-
- /* copy segment, we need this because we still need the old
- * segment when we close the current segment. */
- gst_segment_copy_into (&parse->segment, &seeksegment);
-
- GST_DEBUG_OBJECT (parse, "configuring seek");
- gst_segment_do_seek (&seeksegment, rate, format, flags,
- start_type, start, stop_type, stop, &update);
-
- /* accurate seeking implies seek tables are used to obtain position,
- * and the requested segment is maintained exactly, not adjusted any way */
- accurate = flags & GST_SEEK_FLAG_ACCURATE;
-
- /* maybe we can be accurate for (almost) free */
- gst_base_parse_find_offset (parse, seeksegment.position, TRUE, &start_ts);
- if (seeksegment.position <= start_ts + TARGET_DIFFERENCE) {
- GST_DEBUG_OBJECT (parse, "accurate seek possible");
- accurate = TRUE;
- }
-
- if (accurate) {
- GstClockTime startpos;
- if (rate >= 0)
- startpos = seeksegment.position;
- else
- startpos = start;
-
- /* accurate requested, so ... seek a bit before target */
- if (startpos < parse->priv->lead_in_ts)
- startpos = 0;
- else
- startpos -= parse->priv->lead_in_ts;
-
- if (seeksegment.stop == -1 && seeksegment.duration != -1)
- seeksegment.stop = seeksegment.start + seeksegment.duration;
-
- seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts);
- seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE,
- NULL);
- } else {
- if (rate >= 0)
- start_ts = seeksegment.position;
- else
- start_ts = start;
-
- if (seeksegment.stop == -1 && seeksegment.duration != -1)
- seeksegment.stop = seeksegment.start + seeksegment.duration;
-
- if (!gst_base_parse_convert (parse, format, start_ts,
- GST_FORMAT_BYTES, &seekpos))
- goto convert_failed;
- if (!gst_base_parse_convert (parse, format, seeksegment.stop,
- GST_FORMAT_BYTES, &seekstop))
- goto convert_failed;
- }
-
- GST_DEBUG_OBJECT (parse,
- "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT,
- start_ts, seekpos);
- GST_DEBUG_OBJECT (parse,
- "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT,
- seeksegment.stop, seekstop);
-
- if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
- gint64 last_stop;
-
- GST_DEBUG_OBJECT (parse, "seek in PULL mode");
-
- if (flush) {
- if (parse->srcpad) {
- GstEvent *fevent = gst_event_new_flush_start ();
- GST_DEBUG_OBJECT (parse, "sending flush start");
-
- gst_event_set_seqnum (fevent, seqnum);
-
- gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
- /* unlock upstream pull_range */
- gst_pad_push_event (parse->sinkpad, fevent);
- }
- } else {
- gst_pad_pause_task (parse->sinkpad);
- }
-
- /* we should now be able to grab the streaming thread because we stopped it
- * with the above flush/pause code */
- GST_PAD_STREAM_LOCK (parse->sinkpad);
-
- /* save current position */
- last_stop = parse->segment.position;
- GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT,
- last_stop);
-
- /* now commit to new position */
-
- /* prepare for streaming again */
- if (flush) {
- GstEvent *fevent = gst_event_new_flush_stop (TRUE);
- GST_DEBUG_OBJECT (parse, "sending flush stop");
- gst_event_set_seqnum (fevent, seqnum);
- gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
- gst_pad_push_event (parse->sinkpad, fevent);
- gst_base_parse_clear_queues (parse);
- }
-
- memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
-
- /* store the newsegment event so it can be sent from the streaming thread. */
- /* This will be sent later in _loop() */
- segment_event = gst_event_new_segment (&parse->segment);
- gst_event_set_seqnum (segment_event, seqnum);
- parse->priv->pending_events =
- g_list_prepend (parse->priv->pending_events, segment_event);
-
- GST_DEBUG_OBJECT (parse, "Created newseg format %d, "
- "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
- ", time = %" GST_TIME_FORMAT, format,
- GST_TIME_ARGS (parse->segment.start),
- GST_TIME_ARGS (parse->segment.stop),
- GST_TIME_ARGS (parse->segment.time));
-
- /* one last chance in pull mode to stay accurate;
- * maybe scan and subclass can find where to go */
- if (!accurate) {
- gint64 scanpos;
- GstClockTime ts = seeksegment.position;
-
- gst_base_parse_locate_time (parse, &ts, &scanpos);
- if (scanpos >= 0) {
- accurate = TRUE;
- seekpos = scanpos;
- /* running collected index now consists of several intervals,
- * so optimized check no longer possible */
- parse->priv->index_last_valid = FALSE;
- parse->priv->index_last_offset = 0;
- parse->priv->index_last_ts = 0;
- }
- }
-
- /* mark discont if we are going to stream from another position. */
- if (seekpos != parse->priv->offset) {
- GST_DEBUG_OBJECT (parse,
- "mark DISCONT, we did a seek to another position");
- parse->priv->offset = seekpos;
- parse->priv->last_offset = seekpos;
- parse->priv->seen_keyframe = FALSE;
- parse->priv->discont = TRUE;
- parse->priv->next_dts = start_ts;
- parse->priv->next_pts = GST_CLOCK_TIME_NONE;
- parse->priv->last_dts = GST_CLOCK_TIME_NONE;
- parse->priv->last_pts = GST_CLOCK_TIME_NONE;
- parse->priv->sync_offset = seekpos;
- parse->priv->exact_position = accurate;
- }
-
- /* Start streaming thread if paused */
- gst_pad_start_task (parse->sinkpad,
- (GstTaskFunction) gst_base_parse_loop, parse->sinkpad, NULL);
-
- GST_PAD_STREAM_UNLOCK (parse->sinkpad);
-
- /* handled seek */
- res = TRUE;
- } else {
- GstEvent *new_event;
- GstBaseParseSeek *seek;
- GstSeekFlags flags = (flush ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE);
-
- /* The only thing we need to do in PUSH-mode is to send the
- seek event (in bytes) to upstream. Segment / flush handling happens
- in corresponding src event handlers */
- GST_DEBUG_OBJECT (parse, "seek in PUSH mode");
- if (seekstop >= 0 && seekstop <= seekpos)
- seekstop = seekpos;
- new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
- GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop);
- gst_event_set_seqnum (new_event, seqnum);
-
- /* store segment info so its precise details can be reconstructed when
- * receiving newsegment;
- * this matters for all details when accurate seeking,
- * is most useful to preserve NONE stop time otherwise */
- seek = g_new0 (GstBaseParseSeek, 1);
- seek->segment = seeksegment;
- seek->accurate = accurate;
- seek->offset = seekpos;
- seek->start_ts = start_ts;
- GST_OBJECT_LOCK (parse);
- /* less optimal, but preserves order */
- parse->priv->pending_seeks =
- g_slist_append (parse->priv->pending_seeks, seek);
- GST_OBJECT_UNLOCK (parse);
-
- res = gst_pad_push_event (parse->sinkpad, new_event);
-
- if (!res) {
- GST_OBJECT_LOCK (parse);
- parse->priv->pending_seeks =
- g_slist_remove (parse->priv->pending_seeks, seek);
- GST_OBJECT_UNLOCK (parse);
- g_free (seek);
- }
- }
-
-done:
- gst_event_unref (event);
- return res;
-
- /* ERRORS */
-negative_rate:
- {
- GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream.");
- res = FALSE;
- goto done;
- }
-wrong_type:
- {
- GST_DEBUG_OBJECT (parse, "unsupported seek type.");
- res = FALSE;
- goto done;
- }
-no_convert_to_time:
- {
- GST_DEBUG_OBJECT (parse, "seek in %s format was requested, but subclass "
- "couldn't convert that into TIME format", gst_format_get_name (format));
- res = FALSE;
- goto done;
- }
-convert_failed:
- {
- GST_DEBUG_OBJECT (parse, "conversion TIME to BYTES failed.");
- res = FALSE;
- goto done;
- }
-}
-
-static void
-gst_base_parse_set_upstream_tags (GstBaseParse * parse, GstTagList * taglist)
-{
- if (taglist == parse->priv->upstream_tags)
- return;
-
- if (parse->priv->upstream_tags) {
- gst_tag_list_unref (parse->priv->upstream_tags);
- parse->priv->upstream_tags = NULL;
- }
-
- GST_INFO_OBJECT (parse, "upstream tags: %" GST_PTR_FORMAT, taglist);
-
- if (taglist != NULL)
- parse->priv->upstream_tags = gst_tag_list_ref (taglist);
-
- gst_base_parse_check_bitrate_tags (parse);
-}
-
-#if 0
-static void
-gst_base_parse_set_index (GstElement * element, GstIndex * index)
-{
- GstBaseParse *parse = GST_BASE_PARSE (element);
-
- GST_BASE_PARSE_INDEX_LOCK (parse);
- if (parse->priv->index)
- gst_object_unref (parse->priv->index);
- if (index) {
- parse->priv->index = gst_object_ref (index);
- gst_index_get_writer_id (index, GST_OBJECT_CAST (element),
- &parse->priv->index_id);
- parse->priv->own_index = FALSE;
- } else {
- parse->priv->index = NULL;
- }
- GST_BASE_PARSE_INDEX_UNLOCK (parse);
-}
-
-static GstIndex *
-gst_base_parse_get_index (GstElement * element)
-{
- GstBaseParse *parse = GST_BASE_PARSE (element);
- GstIndex *result = NULL;
-
- GST_BASE_PARSE_INDEX_LOCK (parse);
- if (parse->priv->index)
- result = gst_object_ref (parse->priv->index);
- GST_BASE_PARSE_INDEX_UNLOCK (parse);
-
- return result;
-}
-#endif
-
-static GstStateChangeReturn
-gst_base_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstBaseParse *parse;
- GstStateChangeReturn result;
-
- parse = GST_BASE_PARSE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- /* If this is our own index destroy it as the
- * old entries might be wrong for the new stream */
- GST_BASE_PARSE_INDEX_LOCK (parse);
- if (parse->priv->own_index) {
- gst_object_unref (parse->priv->index);
- parse->priv->index = NULL;
- parse->priv->own_index = FALSE;
- }
-
- /* If no index was created, generate one */
- if (G_UNLIKELY (!parse->priv->index)) {
- GST_DEBUG_OBJECT (parse, "no index provided creating our own");
-
- parse->priv->index = g_object_new (gst_mem_index_get_type (), NULL);
- gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse),
- &parse->priv->index_id);
- parse->priv->own_index = TRUE;
- }
- GST_BASE_PARSE_INDEX_UNLOCK (parse);
- break;
- default:
- break;
- }
-
- result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_base_parse_reset (parse);
- break;
- default:
- break;
- }
-
- return result;
-}
-
-/**
- * gst_base_parse_set_ts_at_offset:
- * @parse: a #GstBaseParse
- * @offset: offset into current buffer
- *
- * This function should only be called from a @handle_frame implementation.
- *
- * #GstBaseParse creates initial timestamps for frames by using the last
- * timestamp seen in the stream before the frame starts. In certain
- * cases, the correct timestamps will occur in the stream after the
- * start of the frame, but before the start of the actual picture data.
- * This function can be used to set the timestamps based on the offset
- * into the frame data that the picture starts.
- *
- * Since: 1.2
- */
-void
-gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset)
-{
- GstClockTime pts, dts;
-
- g_return_if_fail (GST_IS_BASE_PARSE (parse));
-
- pts = gst_adapter_prev_pts_at_offset (parse->priv->adapter, offset, NULL);
- dts = gst_adapter_prev_dts_at_offset (parse->priv->adapter, offset, NULL);
-
- if (!GST_CLOCK_TIME_IS_VALID (pts) || !GST_CLOCK_TIME_IS_VALID (dts)) {
- GST_DEBUG_OBJECT (parse,
- "offset adapter timestamps dts=%" GST_TIME_FORMAT " pts=%"
- GST_TIME_FORMAT, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts));
- }
- if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
- parse->priv->prev_pts = parse->priv->next_pts = pts;
-
- if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) {
- parse->priv->prev_dts = parse->priv->next_dts = dts;
- parse->priv->prev_dts_from_pts = FALSE;
- }
-}
-
-/**
- * gst_base_parse_merge_tags:
- * @parse: a #GstBaseParse
- * @tags: (allow-none): a #GstTagList to merge, or NULL to unset
- * previously-set tags
- * @mode: the #GstTagMergeMode to use, usually #GST_TAG_MERGE_REPLACE
- *
- * Sets the parser subclass's tags and how they should be merged with any
- * upstream stream tags. This will override any tags previously-set
- * with gst_base_parse_merge_tags().
- *
- * Note that this is provided for convenience, and the subclass is
- * not required to use this and can still do tag handling on its own.
- *
- * Since: 1.6
- */
-void
-gst_base_parse_merge_tags (GstBaseParse * parse, GstTagList * tags,
- GstTagMergeMode mode)
-{
- g_return_if_fail (GST_IS_BASE_PARSE (parse));
- g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));
- g_return_if_fail (tags == NULL || mode != GST_TAG_MERGE_UNDEFINED);
-
- GST_OBJECT_LOCK (parse);
-
- if (tags != parse->priv->parser_tags) {
- if (parse->priv->parser_tags) {
- gst_tag_list_unref (parse->priv->parser_tags);
- parse->priv->parser_tags = NULL;
- parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND;
- }
- if (tags) {
- parse->priv->parser_tags = gst_tag_list_ref (tags);
- parse->priv->parser_tags_merge_mode = mode;
- }
-
- GST_DEBUG_OBJECT (parse, "setting parser tags to %" GST_PTR_FORMAT
- " (mode %d)", tags, parse->priv->parser_tags_merge_mode);
-
- gst_base_parse_check_bitrate_tags (parse);
- parse->priv->tags_changed = TRUE;
- }
-
- GST_OBJECT_UNLOCK (parse);
-}
diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h
deleted file mode 100644
index 2614e22f5e..0000000000
--- a/libs/gst/base/gstbaseparse.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/* GStreamer
- * Copyright (C) 2008 Nokia Corporation. All rights reserved.
- *
- * Contact: Stefan Kost <stefan.kost@nokia.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_PARSE_H__
-#define __GST_BASE_PARSE_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_BASE_PARSE (gst_base_parse_get_type())
-#define GST_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_PARSE,GstBaseParse))
-#define GST_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_PARSE,GstBaseParseClass))
-#define GST_BASE_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_PARSE,GstBaseParseClass))
-#define GST_IS_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_PARSE))
-#define GST_IS_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_PARSE))
-#define GST_BASE_PARSE_CAST(obj) ((GstBaseParse *)(obj))
-
-/**
- * GST_BASE_PARSE_SRC_PAD:
- * @obj: base parse instance
- *
- * Gives the pointer to the source #GstPad object of the element.
- */
-#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad)
-
-/**
- * GST_BASE_PARSE_SINK_PAD:
- * @obj: base parse instance
- *
- * Gives the pointer to the sink #GstPad object of the element.
- */
-#define GST_BASE_PARSE_SINK_PAD(obj) (GST_BASE_PARSE_CAST (obj)->sinkpad)
-
-/**
- * GST_BASE_PARSE_FLOW_DROPPED:
- *
- * A #GstFlowReturn that can be returned from
- * #GstBaseParseClass::handle_frame to indicate that no output buffer was
- * generated, or from #GstBaseParseClass::pre_push_frame to to forego
- * pushing buffer.
- */
-#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
-
-/* not public API, use accessor macros below */
-#define GST_BASE_PARSE_FLAG_LOST_SYNC (1 << 0)
-#define GST_BASE_PARSE_FLAG_DRAINING (1 << 1)
-
-/**
- * GST_BASE_PARSE_LOST_SYNC:
- * @parse: base parse instance
- *
- * Obtains current sync status.
- */
-#define GST_BASE_PARSE_LOST_SYNC(parse) (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_LOST_SYNC))
-
-/**
- * GST_BASE_PARSE_DRAINING:
- * @parse: base parse instance
- *
- * Obtains current drain status (ie. whether EOS has been received and
- * the parser is now processing the frames at the end of the stream)
- */
-#define GST_BASE_PARSE_DRAINING(parse) (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_DRAINING))
-
-/**
- * GstBaseParseFrameFlags:
- * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag
- * @GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME: set by baseclass if current frame
- * is passed for processing to the subclass for the first time
- * (and not set on subsequent calls with same data).
- * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be
- * counted as frame, e.g. if this frame is dependent on a previous one.
- * As it is not counted as a frame, bitrate increases but frame to time
- * conversions are maintained.
- * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_frame can set this to indicate
- * that regular segment clipping can still be performed (as opposed to
- * any custom one having been done).
- * @GST_BASE_PARSE_FRAME_FLAG_DROP: indicates to @finish_frame that the
- * the frame should be dropped (and might be handled internally by subclass)
- * @GST_BASE_PARSE_FRAME_FLAG_QUEUE: indicates to @finish_frame that the
- * the frame should be queued for now and processed fully later
- * when the first non-queued frame is finished
- *
- * Flags to be used in a #GstBaseParseFrame.
- */
-typedef enum {
- GST_BASE_PARSE_FRAME_FLAG_NONE = 0,
- GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME = (1 << 0),
- GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 1),
- GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 2),
- GST_BASE_PARSE_FRAME_FLAG_DROP = (1 << 3),
- GST_BASE_PARSE_FRAME_FLAG_QUEUE = (1 << 4)
-} GstBaseParseFrameFlags;
-
-/**
- * GstBaseParseFrame:
- * @buffer: input data to be parsed for frames.
- * @out_buffer: output data.
- * @offset: media specific offset of input frame
- * Note that a converter may have a different one on the frame's buffer.
- * @overhead: subclass can set this to indicates the metadata overhead
- * for the given frame, which is then used to enable more accurate bitrate
- * computations. If this is -1, it is assumed that this frame should be
- * skipped in bitrate calculation.
- * @flags: a combination of input and output #GstBaseParseFrameFlags that
- * convey additional context to subclass or allow subclass to tune
- * subsequent #GstBaseParse actions.
- *
- * Frame (context) data passed to each frame parsing virtual methods. In
- * addition to providing the data to be checked for a valid frame or an already
- * identified frame, it conveys additional metadata or control information
- * from and to the subclass w.r.t. the particular frame in question (rather
- * than global parameters). Some of these may apply to each parsing stage, others
- * only to some a particular one. These parameters are effectively zeroed at start
- * of each frame's processing, i.e. parsing virtual method invocation sequence.
- */
-typedef struct {
- GstBuffer * buffer;
- GstBuffer * out_buffer;
- guint flags;
- guint64 offset;
- gint overhead;
- /*< private >*/
- gint size;
- guint _gst_reserved_i[2];
- gpointer _gst_reserved_p[2];
- guint _private_flags;
-} GstBaseParseFrame;
-
-typedef struct _GstBaseParse GstBaseParse;
-typedef struct _GstBaseParseClass GstBaseParseClass;
-typedef struct _GstBaseParsePrivate GstBaseParsePrivate;
-
-/**
- * GstBaseParse:
- * @element: the parent element.
- *
- * The opaque #GstBaseParse data structure.
- */
-struct _GstBaseParse {
- /*< public >*/
- GstElement element;
-
- /*< protected >*/
- /* source and sink pads */
- GstPad *sinkpad;
- GstPad *srcpad;
-
- guint flags;
-
- /* MT-protected (with STREAM_LOCK) */
- GstSegment segment;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
- GstBaseParsePrivate *priv;
-};
-
-/**
- * GstBaseParseClass:
- * @parent_class: the parent class
- * @start: Optional.
- * Called when the element starts processing.
- * Allows opening external resources.
- * @stop: Optional.
- * Called when the element stops processing.
- * Allows closing external resources.
- * @set_sink_caps: Optional.
- * Allows the subclass to be notified of the actual caps set.
- * @get_sink_caps: Optional.
- * Allows the subclass to do its own sink get caps if needed.
- * @handle_frame: Parses the input data into valid frames as defined by subclass
- * which should be passed to gst_base_parse_finish_frame().
- * The frame's input buffer is guaranteed writable,
- * whereas the input frame ownership is held by caller
- * (so subclass should make a copy if it needs to hang on).
- * Input buffer (data) is provided by baseclass with as much
- * metadata set as possible by baseclass according to upstream
- * information and/or subclass settings,
- * though subclass may still set buffer timestamp and duration
- * if desired.
- * @convert: Optional.
- * Convert between formats.
- * @sink_event: Optional.
- * Event handler on the sink pad. This function should chain
- * up to the parent implementation to let the default handler
- * run.
- * @src_event: Optional.
- * Event handler on the source pad. Should chain up to the
- * parent to let the default handler run.
- * @pre_push_frame: Optional.
- * Called just prior to pushing a frame (after any pending
- * events have been sent) to give subclass a chance to perform
- * additional actions at this time (e.g. tag sending) or to
- * decide whether this buffer should be dropped or not
- * (e.g. custom segment clipping).
- * @detect: Optional.
- * Called until it doesn't return GST_FLOW_OK anymore for
- * the first buffers. Can be used by the subclass to detect
- * the stream format.
- * @sink_query: Optional.
- * Query handler on the sink pad. This function should chain
- * up to the parent implementation to let the default handler
- * run (Since: 1.2)
- * @src_query: Optional.
- * Query handler on the source pad. Should chain up to the
- * parent to let the default handler run (Since: 1.2)
- *
- * Subclasses can override any of the available virtual methods or not, as
- * needed. At minimum @handle_frame needs to be overridden.
- */
-struct _GstBaseParseClass {
- GstElementClass parent_class;
-
- /*< public >*/
- /* virtual methods for subclasses */
-
- gboolean (*start) (GstBaseParse * parse);
-
- gboolean (*stop) (GstBaseParse * parse);
-
- gboolean (*set_sink_caps) (GstBaseParse * parse,
- GstCaps * caps);
-
- GstFlowReturn (*handle_frame) (GstBaseParse * parse,
- GstBaseParseFrame * frame,
- gint * skipsize);
-
- GstFlowReturn (*pre_push_frame) (GstBaseParse * parse,
- GstBaseParseFrame * frame);
-
- gboolean (*convert) (GstBaseParse * parse,
- GstFormat src_format,
- gint64 src_value,
- GstFormat dest_format,
- gint64 * dest_value);
-
- gboolean (*sink_event) (GstBaseParse * parse,
- GstEvent * event);
-
- gboolean (*src_event) (GstBaseParse * parse,
- GstEvent * event);
-
- GstCaps * (*get_sink_caps) (GstBaseParse * parse,
- GstCaps * filter);
-
- GstFlowReturn (*detect) (GstBaseParse * parse,
- GstBuffer * buffer);
-
- gboolean (*sink_query) (GstBaseParse * parse,
- GstQuery * query);
-
- gboolean (*src_query) (GstBaseParse * parse,
- GstQuery * query);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE - 2];
-};
-
-GST_BASE_API
-GType gst_base_parse_get_type (void);
-
-GST_BASE_API
-GType gst_base_parse_frame_get_type (void);
-
-GST_BASE_API
-GstBaseParseFrame * gst_base_parse_frame_new (GstBuffer * buffer,
- GstBaseParseFrameFlags flags,
- gint overhead);
-GST_BASE_API
-void gst_base_parse_frame_init (GstBaseParseFrame * frame);
-
-GST_BASE_API
-GstBaseParseFrame * gst_base_parse_frame_copy (GstBaseParseFrame * frame);
-GST_BASE_API
-void gst_base_parse_frame_free (GstBaseParseFrame * frame);
-
-GST_BASE_API
-GstFlowReturn gst_base_parse_push_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame);
-GST_BASE_API
-GstFlowReturn gst_base_parse_finish_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame,
- gint size);
-GST_BASE_API
-void gst_base_parse_set_duration (GstBaseParse * parse,
- GstFormat fmt,
- gint64 duration,
- gint interval);
-GST_BASE_API
-void gst_base_parse_set_average_bitrate (GstBaseParse * parse,
- guint bitrate);
-GST_BASE_API
-void gst_base_parse_set_min_frame_size (GstBaseParse * parse,
- guint min_size);
-GST_BASE_API
-void gst_base_parse_set_has_timing_info (GstBaseParse * parse,
- gboolean has_timing);
-GST_BASE_API
-void gst_base_parse_drain (GstBaseParse * parse);
-
-GST_BASE_API
-void gst_base_parse_set_syncable (GstBaseParse * parse,
- gboolean syncable);
-GST_BASE_API
-void gst_base_parse_set_passthrough (GstBaseParse * parse,
- gboolean passthrough);
-GST_BASE_API
-void gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
- gboolean pts_interpolate);
-GST_BASE_API
-void gst_base_parse_set_infer_ts (GstBaseParse * parse,
- gboolean infer_ts);
-GST_BASE_API
-void gst_base_parse_set_frame_rate (GstBaseParse * parse,
- guint fps_num,
- guint fps_den,
- guint lead_in,
- guint lead_out);
-GST_BASE_API
-void gst_base_parse_set_latency (GstBaseParse * parse,
- GstClockTime min_latency,
- GstClockTime max_latency);
-GST_BASE_API
-gboolean gst_base_parse_convert_default (GstBaseParse * parse,
- GstFormat src_format,
- gint64 src_value,
- GstFormat dest_format,
- gint64 * dest_value);
-GST_BASE_API
-gboolean gst_base_parse_add_index_entry (GstBaseParse * parse,
- guint64 offset,
- GstClockTime ts,
- gboolean key,
- gboolean force);
-GST_BASE_API
-void gst_base_parse_set_ts_at_offset (GstBaseParse *parse,
- gsize offset);
-GST_BASE_API
-void gst_base_parse_merge_tags (GstBaseParse * parse,
- GstTagList * tags,
- GstTagMergeMode mode);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParseFrame, gst_base_parse_frame_free)
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParse, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_BASE_PARSE_H__ */
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
deleted file mode 100644
index 0a116d6b9b..0000000000
--- a/libs/gst/base/gstbasesink.c
+++ /dev/null
@@ -1,5916 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005-2007 Wim Taymans <wim.taymans@gmail.com>
- *
- * gstbasesink.c: Base class for sink elements
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstbasesink
- * @title: GstBaseSink
- * @short_description: Base class for sink elements
- * @see_also: #GstBaseTransform, #GstBaseSrc
- *
- * #GstBaseSink is the base class for sink elements in GStreamer, such as
- * xvimagesink or filesink. It is a layer on top of #GstElement that provides a
- * simplified interface to plugin writers. #GstBaseSink handles many details
- * for you, for example: preroll, clock synchronization, state changes,
- * activation in push or pull mode, and queries.
- *
- * In most cases, when writing sink elements, there is no need to implement
- * class methods from #GstElement or to set functions on pads, because the
- * #GstBaseSink infrastructure should be sufficient.
- *
- * #GstBaseSink provides support for exactly one sink pad, which should be
- * named "sink". A sink implementation (subclass of #GstBaseSink) should
- * install a pad template in its class_init function, like so:
- * |[<!-- language="C" -->
- * static void
- * my_element_class_init (GstMyElementClass *klass)
- * {
- * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- *
- * // sinktemplate should be a #GstStaticPadTemplate with direction
- * // %GST_PAD_SINK and name "sink"
- * gst_element_class_add_static_pad_template (gstelement_class, &amp;sinktemplate);
- *
- * gst_element_class_set_static_metadata (gstelement_class,
- * "Sink name",
- * "Sink",
- * "My Sink element",
- * "The author <my.sink@my.email>");
- * }
- * ]|
- *
- * #GstBaseSink will handle the prerolling correctly. This means that it will
- * return %GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
- * buffer arrives in this element. The base class will call the
- * #GstBaseSinkClass::preroll vmethod with this preroll buffer and will then
- * commit the state change to the next asynchronously pending state.
- *
- * When the element is set to PLAYING, #GstBaseSink will synchronise on the
- * clock using the times returned from #GstBaseSinkClass::get_times. If this
- * function returns %GST_CLOCK_TIME_NONE for the start time, no synchronisation
- * will be done. Synchronisation can be disabled entirely by setting the object
- * #GstBaseSink:sync property to %FALSE.
- *
- * After synchronisation the virtual method #GstBaseSinkClass::render will be
- * called. Subclasses should minimally implement this method.
- *
- * Subclasses that synchronise on the clock in the #GstBaseSinkClass::render
- * method are supported as well. These classes typically receive a buffer in
- * the render method and can then potentially block on the clock while
- * rendering. A typical example is an audiosink.
- * These subclasses can use gst_base_sink_wait_preroll() to perform the
- * blocking wait.
- *
- * Upon receiving the EOS event in the PLAYING state, #GstBaseSink will wait
- * for the clock to reach the time indicated by the stop time of the last
- * #GstBaseSinkClass::get_times call before posting an EOS message. When the
- * element receives EOS in PAUSED, preroll completes, the event is queued and an
- * EOS message is posted when going to PLAYING.
- *
- * #GstBaseSink will internally use the %GST_EVENT_SEGMENT events to schedule
- * synchronisation and clipping of buffers. Buffers that fall completely outside
- * of the current segment are dropped. Buffers that fall partially in the
- * segment are rendered (and prerolled). Subclasses should do any subbuffer
- * clipping themselves when needed.
- *
- * #GstBaseSink will by default report the current playback position in
- * %GST_FORMAT_TIME based on the current clock time and segment information.
- * If no clock has been set on the element, the query will be forwarded
- * upstream.
- *
- * The #GstBaseSinkClass::set_caps function will be called when the subclass
- * should configure itself to process a specific media type.
- *
- * The #GstBaseSinkClass::start and #GstBaseSinkClass::stop virtual methods
- * will be called when resources should be allocated. Any
- * #GstBaseSinkClass::preroll, #GstBaseSinkClass::render and
- * #GstBaseSinkClass::set_caps function will be called between the
- * #GstBaseSinkClass::start and #GstBaseSinkClass::stop calls.
- *
- * The #GstBaseSinkClass::event virtual method will be called when an event is
- * received by #GstBaseSink. Normally this method should only be overridden by
- * very specific elements (such as file sinks) which need to handle the
- * newsegment event specially.
- *
- * The #GstBaseSinkClass::unlock method is called when the elements should
- * unblock any blocking operations they perform in the
- * #GstBaseSinkClass::render method. This is mostly useful when the
- * #GstBaseSinkClass::render method performs a blocking write on a file
- * descriptor, for example.
- *
- * The #GstBaseSink:max-lateness property affects how the sink deals with
- * buffers that arrive too late in the sink. A buffer arrives too late in the
- * sink when the presentation time (as a combination of the last segment, buffer
- * timestamp and element base_time) plus the duration is before the current
- * time of the clock.
- * If the frame is later than max-lateness, the sink will drop the buffer
- * without calling the render method.
- * This feature is disabled if sync is disabled, the
- * #GstBaseSinkClass::get_times method does not return a valid start time or
- * max-lateness is set to -1 (the default).
- * Subclasses can use gst_base_sink_set_max_lateness() to configure the
- * max-lateness value.
- *
- * The #GstBaseSink:qos property will enable the quality-of-service features of
- * the basesink which gather statistics about the real-time performance of the
- * clock synchronisation. For each buffer received in the sink, statistics are
- * gathered and a QOS event is sent upstream with these numbers. This
- * information can then be used by upstream elements to reduce their processing
- * rate, for example.
- *
- * The #GstBaseSink:async property can be used to instruct the sink to never
- * perform an ASYNC state change. This feature is mostly usable when dealing
- * with non-synchronized streams or sparse streams.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gst/gst_private.h>
-
-#include "gstbasesink.h"
-#include <gst/gst-i18n-lib.h>
-
-GST_DEBUG_CATEGORY_STATIC (gst_base_sink_debug);
-#define GST_CAT_DEFAULT gst_base_sink_debug
-
-#define GST_FLOW_STEP GST_FLOW_CUSTOM_ERROR
-
-typedef struct
-{
- gboolean valid; /* if this info is valid */
- guint32 seqnum; /* the seqnum of the STEP event */
- GstFormat format; /* the format of the amount */
- guint64 amount; /* the total amount of data to skip */
- guint64 position; /* the position in the stepped data */
- guint64 duration; /* the duration in time of the skipped data */
- guint64 start; /* running_time of the start */
- gdouble rate; /* rate of skipping */
- gdouble start_rate; /* rate before skipping */
- guint64 start_start; /* start position skipping */
- guint64 start_stop; /* stop position skipping */
- gboolean flush; /* if this was a flushing step */
- gboolean intermediate; /* if this is an intermediate step */
- gboolean need_preroll; /* if we need preroll after this step */
-} GstStepInfo;
-
-struct _GstBaseSinkPrivate
-{
- gint qos_enabled; /* ATOMIC */
- gboolean async_enabled;
- GstClockTimeDiff ts_offset;
- GstClockTime render_delay;
- GstClockTime processing_deadline;
-
- /* start, stop of current buffer, stream time, used to report position */
- GstClockTime current_sstart;
- GstClockTime current_sstop;
-
- /* start, stop and jitter of current buffer, running time */
- GstClockTime current_rstart;
- GstClockTime current_rstop;
- GstClockTimeDiff current_jitter;
- /* the running time of the previous buffer */
- GstClockTime prev_rstart;
-
- /* EOS sync time in running time */
- GstClockTime eos_rtime;
-
- /* last buffer that arrived in time, running time */
- GstClockTime last_render_time;
- /* when the last buffer left the sink, running time */
- GstClockTime last_left;
-
- /* running averages go here these are done on running time */
- GstClockTime avg_pt, avg_in_diff;
- gdouble avg_rate; /* average with infinite window */
-
- /* number of rendered and dropped frames */
- guint64 rendered;
- guint64 dropped;
-
- /* latency stuff */
- GstClockTime latency;
-
- /* if we already committed the state */
- gboolean committed;
- /* state change to playing ongoing */
- gboolean to_playing;
-
- /* when we received EOS */
- gboolean received_eos;
-
- /* when we are prerolled and able to report latency */
- gboolean have_latency;
-
- /* the last buffer we prerolled or rendered. Useful for making snapshots */
- gint enable_last_sample; /* atomic */
- GstBuffer *last_buffer;
- GstCaps *last_caps;
- GstBufferList *last_buffer_list;
-
- /* negotiated caps */
- GstCaps *caps;
-
- /* blocksize for pulling */
- guint blocksize;
-
- gboolean discont;
-
- /* seqnum of the stream */
- guint32 seqnum;
-
- gboolean call_preroll;
- gboolean step_unlock;
-
- /* we have a pending and a current step operation */
- GstStepInfo current_step;
- GstStepInfo pending_step;
-
- /* instant rate change state */
- /* seqnum of the last instant-rate-sync-time event
- * received. %GST_SEQNUM_INVALID if there isn't one */
- guint32 instant_rate_sync_seqnum;
- /* Active instant-rate multipler. 0.0 if nothing pending */
- gdouble instant_rate_multiplier;
- /* seqnum of the last instant-rate event.
- * %GST_SEQNUM_INVALID if there isn't one */
- guint32 last_instant_rate_seqnum;
- guint32 segment_seqnum;
- GstSegment upstream_segment;
- /* Running time at the start of the last segment event
- * or instant-rate switch in *our* segment, not upstream */
- GstClockTime last_anchor_running_time;
- /* Difference between upstream running time and our own running time
- * at the last segment event or instant-rate switch:
- * upstream + offset = ours */
- GstClockTimeDiff instant_rate_offset;
-
- /* Cached GstClockID */
- GstClockID cached_clock_id;
-
- /* for throttling and QoS */
- GstClockTime earliest_in_time;
- GstClockTime throttle_time;
-
- /* for rate control */
- guint64 max_bitrate;
- GstClockTime rc_time;
- GstClockTime rc_next;
- gsize rc_accumulated;
-
- gboolean drop_out_of_segment;
-};
-
-#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
-
-/* generic running average, this has a neutral window size */
-#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8)
-
-/* the windows for these running averages are experimentally obtained.
- * positive values get averaged more while negative values use a small
- * window so we can react faster to badness. */
-#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
-#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
-
-/* BaseSink properties */
-
-#define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */
-#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
-
-#define DEFAULT_SYNC TRUE
-#define DEFAULT_MAX_LATENESS -1
-#define DEFAULT_QOS FALSE
-#define DEFAULT_ASYNC TRUE
-#define DEFAULT_TS_OFFSET 0
-#define DEFAULT_BLOCKSIZE 4096
-#define DEFAULT_RENDER_DELAY 0
-#define DEFAULT_ENABLE_LAST_SAMPLE TRUE
-#define DEFAULT_THROTTLE_TIME 0
-#define DEFAULT_MAX_BITRATE 0
-#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
-#define DEFAULT_PROCESSING_DEADLINE (20 * GST_MSECOND)
-
-enum
-{
- PROP_0,
- PROP_SYNC,
- PROP_MAX_LATENESS,
- PROP_QOS,
- PROP_ASYNC,
- PROP_TS_OFFSET,
- PROP_ENABLE_LAST_SAMPLE,
- PROP_LAST_SAMPLE,
- PROP_BLOCKSIZE,
- PROP_RENDER_DELAY,
- PROP_THROTTLE_TIME,
- PROP_MAX_BITRATE,
- PROP_PROCESSING_DEADLINE,
- PROP_STATS,
- PROP_LAST
-};
-
-static GstElementClass *parent_class = NULL;
-static gint private_offset = 0;
-
-static void gst_base_sink_class_init (GstBaseSinkClass * klass);
-static void gst_base_sink_init (GstBaseSink * trans, gpointer g_class);
-static void gst_base_sink_finalize (GObject * object);
-
-GType
-gst_base_sink_get_type (void)
-{
- static gsize base_sink_type = 0;
-
- if (g_once_init_enter (&base_sink_type)) {
- GType _type;
- static const GTypeInfo base_sink_info = {
- sizeof (GstBaseSinkClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_base_sink_class_init,
- NULL,
- NULL,
- sizeof (GstBaseSink),
- 0,
- (GInstanceInitFunc) gst_base_sink_init,
- };
-
- _type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstBaseSink", &base_sink_info, G_TYPE_FLAG_ABSTRACT);
-
- private_offset =
- g_type_add_instance_private (_type, sizeof (GstBaseSinkPrivate));
-
- g_once_init_leave (&base_sink_type, _type);
- }
- return base_sink_type;
-}
-
-static inline GstBaseSinkPrivate *
-gst_base_sink_get_instance_private (GstBaseSink * self)
-{
- return (G_STRUCT_MEMBER_P (self, private_offset));
-}
-
-static void gst_base_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_base_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_base_sink_send_event (GstElement * element,
- GstEvent * event);
-static gboolean default_element_query (GstElement * element, GstQuery * query);
-
-static GstCaps *gst_base_sink_default_get_caps (GstBaseSink * sink,
- GstCaps * caps);
-static gboolean gst_base_sink_default_set_caps (GstBaseSink * sink,
- GstCaps * caps);
-static void gst_base_sink_default_get_times (GstBaseSink * basesink,
- GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
-static gboolean gst_base_sink_set_flushing (GstBaseSink * basesink,
- GstPad * pad, gboolean flushing);
-static gboolean gst_base_sink_default_activate_pull (GstBaseSink * basesink,
- gboolean active);
-static gboolean gst_base_sink_default_do_seek (GstBaseSink * sink,
- GstSegment * segment);
-static gboolean gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
- GstEvent * event, GstSegment * segment);
-
-static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,
- GstStateChange transition);
-
-static gboolean gst_base_sink_sink_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstObject * parent,
- GstBuffer * buffer);
-static GstFlowReturn gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
- GstBufferList * list);
-
-static void gst_base_sink_loop (GstPad * pad);
-static gboolean gst_base_sink_pad_activate (GstPad * pad, GstObject * parent);
-static gboolean gst_base_sink_pad_activate_mode (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active);
-static gboolean gst_base_sink_default_event (GstBaseSink * basesink,
- GstEvent * event);
-static GstFlowReturn gst_base_sink_default_wait_event (GstBaseSink * basesink,
- GstEvent * event);
-static gboolean gst_base_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-
-static gboolean gst_base_sink_default_query (GstBaseSink * sink,
- GstQuery * query);
-
-static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
-static GstCaps *gst_base_sink_default_fixate (GstBaseSink * bsink,
- GstCaps * caps);
-static GstCaps *gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
-
-/* check if an object was too late */
-static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,
- GstMiniObject * obj, GstClockTime rstart, GstClockTime rstop,
- GstClockReturn status, GstClockTimeDiff jitter, gboolean render);
-
-static void
-gst_base_sink_class_init (GstBaseSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
- if (private_offset != 0)
- g_type_class_adjust_private_offset (klass, &private_offset);
-
- GST_DEBUG_CATEGORY_INIT (gst_base_sink_debug, "basesink", 0,
- "basesink element");
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_base_sink_finalize;
- gobject_class->set_property = gst_base_sink_set_property;
- gobject_class->get_property = gst_base_sink_get_property;
-
- g_object_class_install_property (gobject_class, PROP_SYNC,
- g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_MAX_LATENESS,
- g_param_spec_int64 ("max-lateness", "Max Lateness",
- "Maximum number of nanoseconds that a buffer can be late before it "
- "is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_QOS,
- g_param_spec_boolean ("qos", "Qos",
- "Generate Quality-of-Service events upstream", DEFAULT_QOS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:async:
- *
- * If set to %TRUE, the basesink will perform asynchronous state changes.
- * When set to %FALSE, the sink will not signal the parent when it prerolls.
- * Use this option when dealing with sparse streams or when synchronisation is
- * not required.
- */
- g_object_class_install_property (gobject_class, PROP_ASYNC,
- g_param_spec_boolean ("async", "Async",
- "Go asynchronously to PAUSED", DEFAULT_ASYNC,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:ts-offset:
- *
- * Controls the final synchronisation, a negative value will render the buffer
- * earlier while a positive value delays playback. This property can be
- * used to fix synchronisation in bad files.
- */
- g_object_class_install_property (gobject_class, PROP_TS_OFFSET,
- g_param_spec_int64 ("ts-offset", "TS Offset",
- "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,
- DEFAULT_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstBaseSink:enable-last-sample:
- *
- * Enable the last-sample property. If %FALSE, basesink doesn't keep a
- * reference to the last buffer arrived and the last-sample property is always
- * set to %NULL. This can be useful if you need buffers to be released as soon
- * as possible, eg. if you're using a buffer pool.
- */
- g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE,
- g_param_spec_boolean ("enable-last-sample", "Enable Last Buffer",
- "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstBaseSink:last-sample:
- *
- * The last buffer that arrived in the sink and was used for preroll or for
- * rendering. This property can be used to generate thumbnails. This property
- * can be %NULL when the sink has not yet received a buffer.
- */
- g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE,
- g_param_spec_boxed ("last-sample", "Last Sample",
- "The last sample received in the sink", GST_TYPE_SAMPLE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:blocksize:
- *
- * The amount of bytes to pull when operating in pull mode.
- */
- /* FIXME 2.0: blocksize property should be int, otherwise min>max.. */
- g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
- g_param_spec_uint ("blocksize", "Block size",
- "Size in bytes to pull per buffer (0 = default)", 0, G_MAXUINT,
- DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:render-delay:
- *
- * The additional delay between synchronisation and actual rendering of the
- * media. This property will add additional latency to the device in order to
- * make other sinks compensate for the delay.
- */
- g_object_class_install_property (gobject_class, PROP_RENDER_DELAY,
- g_param_spec_uint64 ("render-delay", "Render Delay",
- "Additional render delay of the sink in nanoseconds", 0, G_MAXUINT64,
- DEFAULT_RENDER_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:throttle-time:
- *
- * The time to insert between buffers. This property can be used to control
- * the maximum amount of buffers per second to render. Setting this property
- * to a value bigger than 0 will make the sink create THROTTLE QoS events.
- */
- g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME,
- g_param_spec_uint64 ("throttle-time", "Throttle time",
- "The time to keep between rendered buffers (0 = disabled)", 0,
- G_MAXUINT64, DEFAULT_THROTTLE_TIME,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:max-bitrate:
- *
- * Control the maximum amount of bits that will be rendered per second.
- * Setting this property to a value bigger than 0 will make the sink delay
- * rendering of the buffers when it would exceed to max-bitrate.
- *
- * Since: 1.2
- */
- g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
- g_param_spec_uint64 ("max-bitrate", "Max Bitrate",
- "The maximum bits per second to render (0 = disabled)", 0,
- G_MAXUINT64, DEFAULT_MAX_BITRATE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- /**
- * GstBaseSink:processing-deadline:
- *
- * Maximum amount of time (in nanoseconds) that the pipeline can take
- * for processing the buffer. This is added to the latency of live
- * pipelines.
- *
- * Since: 1.16
- */
- g_object_class_install_property (gobject_class, PROP_PROCESSING_DEADLINE,
- g_param_spec_uint64 ("processing-deadline", "Processing deadline",
- "Maximum processing time for a buffer in nanoseconds", 0,
- G_MAXUINT64, DEFAULT_PROCESSING_DEADLINE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-
- /**
- * GstBaseSink:stats:
- *
- * Various #GstBaseSink statistics. This property returns a #GstStructure
- * with name `application/x-gst-base-sink-stats` with the following fields:
- *
- * - "average-rate" G_TYPE_DOUBLE average frame rate
- * - "dropped" G_TYPE_UINT64 Number of dropped frames
- * - "rendered" G_TYPE_UINT64 Number of rendered frames
- *
- * Since: 1.18
- */
- g_object_class_install_property (gobject_class, PROP_STATS,
- g_param_spec_boxed ("stats", "Statistics",
- "Sink Statistics", GST_TYPE_STRUCTURE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
- gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
- gstelement_class->query = GST_DEBUG_FUNCPTR (default_element_query);
-
- klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_caps);
- klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_set_caps);
- klass->fixate = GST_DEBUG_FUNCPTR (gst_base_sink_default_fixate);
- klass->activate_pull =
- GST_DEBUG_FUNCPTR (gst_base_sink_default_activate_pull);
- klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_times);
- klass->query = GST_DEBUG_FUNCPTR (gst_base_sink_default_query);
- klass->event = GST_DEBUG_FUNCPTR (gst_base_sink_default_event);
- klass->wait_event = GST_DEBUG_FUNCPTR (gst_base_sink_default_wait_event);
-
- /* Registering debug symbols for function pointers */
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_fixate);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_mode);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_event);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain_list);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_sink_query);
-}
-
-static GstCaps *
-gst_base_sink_query_caps (GstBaseSink * bsink, GstPad * pad, GstCaps * filter)
-{
- GstBaseSinkClass *bclass;
- GstCaps *caps = NULL;
- gboolean fixed;
-
- bclass = GST_BASE_SINK_GET_CLASS (bsink);
- fixed = GST_PAD_IS_FIXED_CAPS (pad);
-
- if (fixed || bsink->pad_mode == GST_PAD_MODE_PULL) {
- /* if we are operating in pull mode or fixed caps, we only accept the
- * currently negotiated caps */
- caps = gst_pad_get_current_caps (pad);
- }
- if (caps == NULL) {
- if (bclass->get_caps)
- caps = bclass->get_caps (bsink, filter);
-
- if (caps == NULL) {
- GstPadTemplate *pad_template;
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass),
- "sink");
- if (pad_template != NULL) {
- caps = gst_pad_template_get_caps (pad_template);
-
- if (filter) {
- GstCaps *intersection;
-
- intersection =
- gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (caps);
- caps = intersection;
- }
- }
- }
- }
-
- return caps;
-}
-
-static GstCaps *
-gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps)
-{
- GST_DEBUG_OBJECT (bsink, "using default caps fixate function");
- return gst_caps_fixate (caps);
-}
-
-static GstCaps *
-gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
-{
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (bsink);
-
- if (bclass->fixate)
- caps = bclass->fixate (bsink, caps);
-
- return caps;
-}
-
-static void
-gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
-{
- GstPadTemplate *pad_template;
- GstBaseSinkPrivate *priv;
-
- basesink->priv = priv = gst_base_sink_get_instance_private (basesink);
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink");
- g_return_if_fail (pad_template != NULL);
-
- basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink");
-
- gst_pad_set_activate_function (basesink->sinkpad, gst_base_sink_pad_activate);
- gst_pad_set_activatemode_function (basesink->sinkpad,
- gst_base_sink_pad_activate_mode);
- gst_pad_set_query_function (basesink->sinkpad, gst_base_sink_sink_query);
- gst_pad_set_event_function (basesink->sinkpad, gst_base_sink_event);
- gst_pad_set_chain_function (basesink->sinkpad, gst_base_sink_chain);
- gst_pad_set_chain_list_function (basesink->sinkpad, gst_base_sink_chain_list);
- gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad);
-
- basesink->pad_mode = GST_PAD_MODE_NONE;
- g_mutex_init (&basesink->preroll_lock);
- g_cond_init (&basesink->preroll_cond);
- priv->have_latency = FALSE;
-
- basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH;
- basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
-
- basesink->sync = DEFAULT_SYNC;
- basesink->max_lateness = DEFAULT_MAX_LATENESS;
- g_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS);
- priv->async_enabled = DEFAULT_ASYNC;
- priv->ts_offset = DEFAULT_TS_OFFSET;
- priv->render_delay = DEFAULT_RENDER_DELAY;
- priv->processing_deadline = DEFAULT_PROCESSING_DEADLINE;
- priv->blocksize = DEFAULT_BLOCKSIZE;
- priv->cached_clock_id = NULL;
- g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE);
- priv->throttle_time = DEFAULT_THROTTLE_TIME;
- priv->max_bitrate = DEFAULT_MAX_BITRATE;
-
- priv->drop_out_of_segment = DEFAULT_DROP_OUT_OF_SEGMENT;
-
- GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_SINK);
-}
-
-static void
-gst_base_sink_finalize (GObject * object)
-{
- GstBaseSink *basesink;
-
- basesink = GST_BASE_SINK (object);
-
- g_mutex_clear (&basesink->preroll_lock);
- g_cond_clear (&basesink->preroll_cond);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/**
- * gst_base_sink_set_sync:
- * @sink: the sink
- * @sync: the new sync value.
- *
- * Configures @sink to synchronize on the clock or not. When
- * @sync is %FALSE, incoming samples will be played as fast as
- * possible. If @sync is %TRUE, the timestamps of the incoming
- * buffers will be used to schedule the exact render time of its
- * contents.
- */
-void
-gst_base_sink_set_sync (GstBaseSink * sink, gboolean sync)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->sync = sync;
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_sync:
- * @sink: the sink
- *
- * Checks if @sink is currently configured to synchronize against the
- * clock.
- *
- * Returns: %TRUE if the sink is configured to synchronize against the clock.
- */
-gboolean
-gst_base_sink_get_sync (GstBaseSink * sink)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
-
- GST_OBJECT_LOCK (sink);
- res = sink->sync;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_drop_out_of_segment:
- * @sink: the sink
- * @drop_out_of_segment: drop buffers outside the segment
- *
- * Configure @sink to drop buffers which are outside the current segment
- *
- * Since: 1.12
- */
-void
-gst_base_sink_set_drop_out_of_segment (GstBaseSink * sink,
- gboolean drop_out_of_segment)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->priv->drop_out_of_segment = drop_out_of_segment;
- GST_OBJECT_UNLOCK (sink);
-
-}
-
-/**
- * gst_base_sink_get_drop_out_of_segment:
- * @sink: the sink
- *
- * Checks if @sink is currently configured to drop buffers which are outside
- * the current segment
- *
- * Returns: %TRUE if the sink is configured to drop buffers outside the
- * current segment.
- *
- * Since: 1.12
- */
-gboolean
-gst_base_sink_get_drop_out_of_segment (GstBaseSink * sink)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->drop_out_of_segment;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_max_lateness:
- * @sink: the sink
- * @max_lateness: the new max lateness value.
- *
- * Sets the new max lateness value to @max_lateness. This value is
- * used to decide if a buffer should be dropped or not based on the
- * buffer timestamp and the current clock time. A value of -1 means
- * an unlimited time.
- */
-void
-gst_base_sink_set_max_lateness (GstBaseSink * sink, gint64 max_lateness)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->max_lateness = max_lateness;
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_max_lateness:
- * @sink: the sink
- *
- * Gets the max lateness value. See gst_base_sink_set_max_lateness() for
- * more details.
- *
- * Returns: The maximum time in nanoseconds that a buffer can be late
- * before it is dropped and not rendered. A value of -1 means an
- * unlimited time.
- */
-gint64
-gst_base_sink_get_max_lateness (GstBaseSink * sink)
-{
- gint64 res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), -1);
-
- GST_OBJECT_LOCK (sink);
- res = sink->max_lateness;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_qos_enabled:
- * @sink: the sink
- * @enabled: the new qos value.
- *
- * Configures @sink to send Quality-of-Service events upstream.
- */
-void
-gst_base_sink_set_qos_enabled (GstBaseSink * sink, gboolean enabled)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- g_atomic_int_set (&sink->priv->qos_enabled, enabled);
-}
-
-/**
- * gst_base_sink_is_qos_enabled:
- * @sink: the sink
- *
- * Checks if @sink is currently configured to send Quality-of-Service events
- * upstream.
- *
- * Returns: %TRUE if the sink is configured to perform Quality-of-Service.
- */
-gboolean
-gst_base_sink_is_qos_enabled (GstBaseSink * sink)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
-
- res = g_atomic_int_get (&sink->priv->qos_enabled);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_async_enabled:
- * @sink: the sink
- * @enabled: the new async value.
- *
- * Configures @sink to perform all state changes asynchronously. When async is
- * disabled, the sink will immediately go to PAUSED instead of waiting for a
- * preroll buffer. This feature is useful if the sink does not synchronize
- * against the clock or when it is dealing with sparse streams.
- */
-void
-gst_base_sink_set_async_enabled (GstBaseSink * sink, gboolean enabled)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_BASE_SINK_PREROLL_LOCK (sink);
- g_atomic_int_set (&sink->priv->async_enabled, enabled);
- GST_LOG_OBJECT (sink, "set async enabled to %d", enabled);
- GST_BASE_SINK_PREROLL_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_is_async_enabled:
- * @sink: the sink
- *
- * Checks if @sink is currently configured to perform asynchronous state
- * changes to PAUSED.
- *
- * Returns: %TRUE if the sink is configured to perform asynchronous state
- * changes.
- */
-gboolean
-gst_base_sink_is_async_enabled (GstBaseSink * sink)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
-
- res = g_atomic_int_get (&sink->priv->async_enabled);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_ts_offset:
- * @sink: the sink
- * @offset: the new offset
- *
- * Adjust the synchronisation of @sink with @offset. A negative value will
- * render buffers earlier than their timestamp. A positive value will delay
- * rendering. This function can be used to fix playback of badly timestamped
- * buffers.
- */
-void
-gst_base_sink_set_ts_offset (GstBaseSink * sink, GstClockTimeDiff offset)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->priv->ts_offset = offset;
- GST_LOG_OBJECT (sink, "set time offset to %" G_GINT64_FORMAT, offset);
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_ts_offset:
- * @sink: the sink
- *
- * Get the synchronisation offset of @sink.
- *
- * Returns: The synchronisation offset.
- */
-GstClockTimeDiff
-gst_base_sink_get_ts_offset (GstBaseSink * sink)
-{
- GstClockTimeDiff res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->ts_offset;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_get_last_sample:
- * @sink: the sink
- *
- * Get the last sample that arrived in the sink and was used for preroll or for
- * rendering. This property can be used to generate thumbnails.
- *
- * The #GstCaps on the sample can be used to determine the type of the buffer.
- *
- * Free-function: gst_sample_unref
- *
- * Returns: (transfer full) (nullable): a #GstSample. gst_sample_unref() after
- * usage. This function returns %NULL when no buffer has arrived in the
- * sink yet or when the sink is not in PAUSED or PLAYING.
- */
-GstSample *
-gst_base_sink_get_last_sample (GstBaseSink * sink)
-{
- GstSample *res = NULL;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), NULL);
-
- GST_OBJECT_LOCK (sink);
- if (sink->priv->last_buffer_list) {
- GstBuffer *first_buffer = NULL;
-
- /* Set the first buffer in the list to last sample's buffer */
- first_buffer = gst_buffer_list_get (sink->priv->last_buffer_list, 0);
- res =
- gst_sample_new (first_buffer, sink->priv->last_caps, &sink->segment,
- NULL);
- gst_sample_set_buffer_list (res, sink->priv->last_buffer_list);
- } else if (sink->priv->last_buffer) {
- res = gst_sample_new (sink->priv->last_buffer,
- sink->priv->last_caps, &sink->segment, NULL);
- }
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/* with OBJECT_LOCK */
-static void
-gst_base_sink_set_last_buffer_unlocked (GstBaseSink * sink, GstBuffer * buffer)
-{
- GstBuffer *old;
-
- old = sink->priv->last_buffer;
- if (G_LIKELY (old != buffer)) {
- GST_DEBUG_OBJECT (sink, "setting last buffer to %p", buffer);
- if (G_LIKELY (buffer))
- gst_buffer_ref (buffer);
- sink->priv->last_buffer = buffer;
- if (buffer)
- /* copy over the caps */
- gst_caps_replace (&sink->priv->last_caps, sink->priv->caps);
- else
- gst_caps_replace (&sink->priv->last_caps, NULL);
- } else {
- old = NULL;
- }
- /* avoid unreffing with the lock because cleanup code might want to take the
- * lock too */
- if (G_LIKELY (old)) {
- GST_OBJECT_UNLOCK (sink);
- gst_buffer_unref (old);
- GST_OBJECT_LOCK (sink);
- }
-}
-
-/* with OBJECT_LOCK */
-static void
-gst_base_sink_set_last_buffer_list_unlocked (GstBaseSink * sink,
- GstBufferList * buffer_list)
-{
- GstBufferList *old;
-
- old = sink->priv->last_buffer_list;
- if (G_LIKELY (old != buffer_list)) {
- GST_DEBUG_OBJECT (sink, "setting last buffer list to %p", buffer_list);
- if (G_LIKELY (buffer_list))
- gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer_list));
- sink->priv->last_buffer_list = buffer_list;
- } else {
- old = NULL;
- }
-
- /* avoid unreffing with the lock because cleanup code might want to take the
- * lock too */
- if (G_LIKELY (old)) {
- GST_OBJECT_UNLOCK (sink);
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (old));
- GST_OBJECT_LOCK (sink);
- }
-}
-
-static void
-gst_base_sink_set_last_buffer (GstBaseSink * sink, GstBuffer * buffer)
-{
- if (!g_atomic_int_get (&sink->priv->enable_last_sample))
- return;
-
- GST_OBJECT_LOCK (sink);
- gst_base_sink_set_last_buffer_unlocked (sink, buffer);
- GST_OBJECT_UNLOCK (sink);
-}
-
-static void
-gst_base_sink_set_last_buffer_list (GstBaseSink * sink,
- GstBufferList * buffer_list)
-{
- if (!g_atomic_int_get (&sink->priv->enable_last_sample))
- return;
-
- GST_OBJECT_LOCK (sink);
- gst_base_sink_set_last_buffer_list_unlocked (sink, buffer_list);
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_set_last_sample_enabled:
- * @sink: the sink
- * @enabled: the new enable-last-sample value.
- *
- * Configures @sink to store the last received sample in the last-sample
- * property.
- */
-void
-gst_base_sink_set_last_sample_enabled (GstBaseSink * sink, gboolean enabled)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- /* Only take lock if we change the value */
- if (g_atomic_int_compare_and_exchange (&sink->priv->enable_last_sample,
- !enabled, enabled) && !enabled) {
- GST_OBJECT_LOCK (sink);
- gst_base_sink_set_last_buffer_unlocked (sink, NULL);
- gst_base_sink_set_last_buffer_list_unlocked (sink, NULL);
- GST_OBJECT_UNLOCK (sink);
- }
-}
-
-/**
- * gst_base_sink_is_last_sample_enabled:
- * @sink: the sink
- *
- * Checks if @sink is currently configured to store the last received sample in
- * the last-sample property.
- *
- * Returns: %TRUE if the sink is configured to store the last received sample.
- */
-gboolean
-gst_base_sink_is_last_sample_enabled (GstBaseSink * sink)
-{
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
-
- return g_atomic_int_get (&sink->priv->enable_last_sample);
-}
-
-/**
- * gst_base_sink_get_latency:
- * @sink: the sink
- *
- * Get the currently configured latency.
- *
- * Returns: The configured latency.
- */
-GstClockTime
-gst_base_sink_get_latency (GstBaseSink * sink)
-{
- GstClockTime res;
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->latency;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_query_latency:
- * @sink: the sink
- * @live: (out) (allow-none): if the sink is live
- * @upstream_live: (out) (allow-none): if an upstream element is live
- * @min_latency: (out) (allow-none): the min latency of the upstream elements
- * @max_latency: (out) (allow-none): the max latency of the upstream elements
- *
- * Query the sink for the latency parameters. The latency will be queried from
- * the upstream elements. @live will be %TRUE if @sink is configured to
- * synchronize against the clock. @upstream_live will be %TRUE if an upstream
- * element is live.
- *
- * If both @live and @upstream_live are %TRUE, the sink will want to compensate
- * for the latency introduced by the upstream elements by setting the
- * @min_latency to a strictly positive value.
- *
- * This function is mostly used by subclasses.
- *
- * Returns: %TRUE if the query succeeded.
- */
-gboolean
-gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
- gboolean * upstream_live, GstClockTime * min_latency,
- GstClockTime * max_latency)
-{
- gboolean l, us_live, res, have_latency;
- GstClockTime min, max, render_delay, processing_deadline;
- GstQuery *query;
- GstClockTime us_min, us_max;
-
- /* we are live when we sync to the clock */
- GST_OBJECT_LOCK (sink);
- l = sink->sync;
- have_latency = sink->priv->have_latency;
- render_delay = sink->priv->render_delay;
- processing_deadline = sink->priv->processing_deadline;
- GST_OBJECT_UNLOCK (sink);
-
- /* assume no latency */
- min = 0;
- max = -1;
- us_live = FALSE;
- us_min = 0;
- us_max = 0;
-
- if (have_latency) {
- GST_DEBUG_OBJECT (sink, "we are ready for LATENCY query");
- /* we are ready for a latency query this is when we preroll or when we are
- * not async. */
- query = gst_query_new_latency ();
-
- /* ask the peer for the latency */
- if ((res = gst_pad_peer_query (sink->sinkpad, query))) {
- /* get upstream min and max latency */
- gst_query_parse_latency (query, &us_live, &us_min, &us_max);
-
- if (us_live) {
- /* upstream live, use its latency, subclasses should use these
- * values to create the complete latency. */
- min = us_min;
- max = us_max;
-
- if (l) {
- if (max == -1 || min + processing_deadline <= max)
- min += processing_deadline;
- else {
- GST_ELEMENT_WARNING (sink, CORE, CLOCK,
- (_("Pipeline construction is invalid, please add queues.")),
- ("Not enough buffering available for "
- " the processing deadline of %" GST_TIME_FORMAT
- ", add enough queues to buffer %" GST_TIME_FORMAT
- " additional data. Shortening processing latency to %"
- GST_TIME_FORMAT ".",
- GST_TIME_ARGS (processing_deadline),
- GST_TIME_ARGS (min + processing_deadline - max),
- GST_TIME_ARGS (max - min)));
- min = max;
- }
- }
- }
- if (l) {
- /* we need to add the render delay if we are live */
- min += render_delay;
- if (max != -1)
- max += render_delay;
- }
- }
- gst_query_unref (query);
- } else {
- GST_DEBUG_OBJECT (sink, "we are not yet ready for LATENCY query");
- res = FALSE;
- }
-
- /* not live, we tried to do the query, if it failed we return TRUE anyway */
- if (!res) {
- if (!l) {
- res = TRUE;
- GST_DEBUG_OBJECT (sink, "latency query failed but we are not live");
- } else {
- GST_DEBUG_OBJECT (sink, "latency query failed and we are live");
- }
- }
-
- if (res) {
- GST_DEBUG_OBJECT (sink, "latency query: live: %d, have_latency %d,"
- " upstream_live %d, min(%" GST_TIME_FORMAT ")=upstream(%"
- GST_TIME_FORMAT ")+processing_deadline(%" GST_TIME_FORMAT
- ")+render_delay(%" GST_TIME_FORMAT "), max(%" GST_TIME_FORMAT
- ")=upstream(%" GST_TIME_FORMAT ")+render_delay(%" GST_TIME_FORMAT ")",
- l, have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (us_min),
- GST_TIME_ARGS (processing_deadline), GST_TIME_ARGS (render_delay),
- GST_TIME_ARGS (max), GST_TIME_ARGS (us_max),
- GST_TIME_ARGS (render_delay));
-
- if (live)
- *live = l;
- if (upstream_live)
- *upstream_live = us_live;
- if (min_latency)
- *min_latency = min;
- if (max_latency)
- *max_latency = max;
- }
- return res;
-}
-
-/**
- * gst_base_sink_set_render_delay:
- * @sink: a #GstBaseSink
- * @delay: the new delay
- *
- * Set the render delay in @sink to @delay. The render delay is the time
- * between actual rendering of a buffer and its synchronisation time. Some
- * devices might delay media rendering which can be compensated for with this
- * function.
- *
- * After calling this function, this sink will report additional latency and
- * other sinks will adjust their latency to delay the rendering of their media.
- *
- * This function is usually called by subclasses.
- */
-void
-gst_base_sink_set_render_delay (GstBaseSink * sink, GstClockTime delay)
-{
- GstClockTime old_render_delay;
-
- g_return_if_fail (GST_IS_BASE_SINK (sink));
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (delay));
-
- GST_OBJECT_LOCK (sink);
- old_render_delay = sink->priv->render_delay;
- sink->priv->render_delay = delay;
- GST_LOG_OBJECT (sink, "set render delay to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (delay));
- GST_OBJECT_UNLOCK (sink);
-
- if (delay != old_render_delay) {
- GST_DEBUG_OBJECT (sink, "posting latency changed");
- gst_element_post_message (GST_ELEMENT_CAST (sink),
- gst_message_new_latency (GST_OBJECT_CAST (sink)));
- }
-}
-
-/**
- * gst_base_sink_get_render_delay:
- * @sink: a #GstBaseSink
- *
- * Get the render delay of @sink. see gst_base_sink_set_render_delay() for more
- * information about the render delay.
- *
- * Returns: the render delay of @sink.
- */
-GstClockTime
-gst_base_sink_get_render_delay (GstBaseSink * sink)
-{
- GstClockTimeDiff res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->render_delay;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_blocksize:
- * @sink: a #GstBaseSink
- * @blocksize: the blocksize in bytes
- *
- * Set the number of bytes that the sink will pull when it is operating in pull
- * mode.
- */
-/* FIXME 2.0: blocksize property should be int, otherwise min>max.. */
-void
-gst_base_sink_set_blocksize (GstBaseSink * sink, guint blocksize)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->priv->blocksize = blocksize;
- GST_LOG_OBJECT (sink, "set blocksize to %u", blocksize);
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_blocksize:
- * @sink: a #GstBaseSink
- *
- * Get the number of bytes that the sink will pull when it is operating in pull
- * mode.
- *
- * Returns: the number of bytes @sink will pull in pull mode.
- */
-/* FIXME 2.0: blocksize property should be int, otherwise min>max.. */
-guint
-gst_base_sink_get_blocksize (GstBaseSink * sink)
-{
- guint res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->blocksize;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_throttle_time:
- * @sink: a #GstBaseSink
- * @throttle: the throttle time in nanoseconds
- *
- * Set the time that will be inserted between rendered buffers. This
- * can be used to control the maximum buffers per second that the sink
- * will render.
- */
-void
-gst_base_sink_set_throttle_time (GstBaseSink * sink, guint64 throttle)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->priv->throttle_time = throttle;
- GST_LOG_OBJECT (sink, "set throttle_time to %" G_GUINT64_FORMAT, throttle);
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_throttle_time:
- * @sink: a #GstBaseSink
- *
- * Get the time that will be inserted between frames to control the
- * maximum buffers per second.
- *
- * Returns: the number of nanoseconds @sink will put between frames.
- */
-guint64
-gst_base_sink_get_throttle_time (GstBaseSink * sink)
-{
- guint64 res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->throttle_time;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_max_bitrate:
- * @sink: a #GstBaseSink
- * @max_bitrate: the max_bitrate in bits per second
- *
- * Set the maximum amount of bits per second that the sink will render.
- *
- * Since: 1.2
- */
-void
-gst_base_sink_set_max_bitrate (GstBaseSink * sink, guint64 max_bitrate)
-{
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- sink->priv->max_bitrate = max_bitrate;
- GST_LOG_OBJECT (sink, "set max_bitrate to %" G_GUINT64_FORMAT, max_bitrate);
- GST_OBJECT_UNLOCK (sink);
-}
-
-/**
- * gst_base_sink_get_max_bitrate:
- * @sink: a #GstBaseSink
- *
- * Get the maximum amount of bits per second that the sink will render.
- *
- * Returns: the maximum number of bits per second @sink will render.
- *
- * Since: 1.2
- */
-guint64
-gst_base_sink_get_max_bitrate (GstBaseSink * sink)
-{
- guint64 res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->max_bitrate;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-/**
- * gst_base_sink_set_processing_deadline:
- * @sink: a #GstBaseSink
- * @processing_deadline: the new processing deadline in nanoseconds.
- *
- * Maximum amount of time (in nanoseconds) that the pipeline can take
- * for processing the buffer. This is added to the latency of live
- * pipelines.
- *
- * This function is usually called by subclasses.
- *
- * Since: 1.16
- */
-void
-gst_base_sink_set_processing_deadline (GstBaseSink * sink,
- GstClockTime processing_deadline)
-{
- GstClockTime old_processing_deadline;
-
- g_return_if_fail (GST_IS_BASE_SINK (sink));
-
- GST_OBJECT_LOCK (sink);
- old_processing_deadline = sink->priv->processing_deadline;
- sink->priv->processing_deadline = processing_deadline;
- GST_LOG_OBJECT (sink, "set render processing_deadline to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (processing_deadline));
- GST_OBJECT_UNLOCK (sink);
-
- if (processing_deadline != old_processing_deadline) {
- GST_DEBUG_OBJECT (sink, "posting latency changed");
- gst_element_post_message (GST_ELEMENT_CAST (sink),
- gst_message_new_latency (GST_OBJECT_CAST (sink)));
- }
-}
-
-/**
- * gst_base_sink_get_processing_deadline:
- * @sink: a #GstBaseSink
- *
- * Get the processing deadline of @sink. see
- * gst_base_sink_set_processing_deadline() for more information about
- * the processing deadline.
- *
- * Returns: the processing deadline
- *
- * Since: 1.16
- */
-GstClockTime
-gst_base_sink_get_processing_deadline (GstBaseSink * sink)
-{
- GstClockTimeDiff res;
-
- g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
-
- GST_OBJECT_LOCK (sink);
- res = sink->priv->processing_deadline;
- GST_OBJECT_UNLOCK (sink);
-
- return res;
-}
-
-static void
-gst_base_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstBaseSink *sink = GST_BASE_SINK (object);
-
- switch (prop_id) {
- case PROP_SYNC:
- gst_base_sink_set_sync (sink, g_value_get_boolean (value));
- break;
- case PROP_MAX_LATENESS:
- gst_base_sink_set_max_lateness (sink, g_value_get_int64 (value));
- break;
- case PROP_QOS:
- gst_base_sink_set_qos_enabled (sink, g_value_get_boolean (value));
- break;
- case PROP_ASYNC:
- gst_base_sink_set_async_enabled (sink, g_value_get_boolean (value));
- break;
- case PROP_TS_OFFSET:
- gst_base_sink_set_ts_offset (sink, g_value_get_int64 (value));
- break;
- case PROP_BLOCKSIZE:
- gst_base_sink_set_blocksize (sink, g_value_get_uint (value));
- break;
- case PROP_RENDER_DELAY:
- gst_base_sink_set_render_delay (sink, g_value_get_uint64 (value));
- break;
- case PROP_ENABLE_LAST_SAMPLE:
- gst_base_sink_set_last_sample_enabled (sink, g_value_get_boolean (value));
- break;
- case PROP_THROTTLE_TIME:
- gst_base_sink_set_throttle_time (sink, g_value_get_uint64 (value));
- break;
- case PROP_MAX_BITRATE:
- gst_base_sink_set_max_bitrate (sink, g_value_get_uint64 (value));
- break;
- case PROP_PROCESSING_DEADLINE:
- gst_base_sink_set_processing_deadline (sink, g_value_get_uint64 (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstBaseSink *sink = GST_BASE_SINK (object);
-
- switch (prop_id) {
- case PROP_SYNC:
- g_value_set_boolean (value, gst_base_sink_get_sync (sink));
- break;
- case PROP_MAX_LATENESS:
- g_value_set_int64 (value, gst_base_sink_get_max_lateness (sink));
- break;
- case PROP_QOS:
- g_value_set_boolean (value, gst_base_sink_is_qos_enabled (sink));
- break;
- case PROP_ASYNC:
- g_value_set_boolean (value, gst_base_sink_is_async_enabled (sink));
- break;
- case PROP_TS_OFFSET:
- g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink));
- break;
- case PROP_LAST_SAMPLE:
- gst_value_take_sample (value, gst_base_sink_get_last_sample (sink));
- break;
- case PROP_ENABLE_LAST_SAMPLE:
- g_value_set_boolean (value, gst_base_sink_is_last_sample_enabled (sink));
- break;
- case PROP_BLOCKSIZE:
- g_value_set_uint (value, gst_base_sink_get_blocksize (sink));
- break;
- case PROP_RENDER_DELAY:
- g_value_set_uint64 (value, gst_base_sink_get_render_delay (sink));
- break;
- case PROP_THROTTLE_TIME:
- g_value_set_uint64 (value, gst_base_sink_get_throttle_time (sink));
- break;
- case PROP_MAX_BITRATE:
- g_value_set_uint64 (value, gst_base_sink_get_max_bitrate (sink));
- break;
- case PROP_PROCESSING_DEADLINE:
- g_value_set_uint64 (value, gst_base_sink_get_processing_deadline (sink));
- break;
- case PROP_STATS:
- g_value_take_boxed (value, gst_base_sink_get_stats (sink));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static GstCaps *
-gst_base_sink_default_get_caps (GstBaseSink * sink, GstCaps * filter)
-{
- return NULL;
-}
-
-static gboolean
-gst_base_sink_default_set_caps (GstBaseSink * sink, GstCaps * caps)
-{
- return TRUE;
-}
-
-/* with PREROLL_LOCK, STREAM_LOCK */
-static gboolean
-gst_base_sink_commit_state (GstBaseSink * basesink)
-{
- /* commit state and proceed to next pending state */
- GstState current, next, pending, post_pending;
- gboolean post_paused = FALSE;
- gboolean post_async_done = FALSE;
- gboolean post_playing = FALSE;
-
- /* we are certainly not playing async anymore now */
- basesink->playing_async = FALSE;
-
- GST_OBJECT_LOCK (basesink);
- current = GST_STATE (basesink);
- next = GST_STATE_NEXT (basesink);
- pending = GST_STATE_PENDING (basesink);
- post_pending = pending;
-
- switch (pending) {
- case GST_STATE_PLAYING:
- {
- GST_DEBUG_OBJECT (basesink, "committing state to PLAYING");
-
- basesink->need_preroll = FALSE;
- post_async_done = TRUE;
- basesink->priv->committed = TRUE;
- post_playing = TRUE;
- /* post PAUSED too when we were READY */
- if (current == GST_STATE_READY) {
- post_paused = TRUE;
- }
- break;
- }
- case GST_STATE_PAUSED:
- GST_DEBUG_OBJECT (basesink, "committing state to PAUSED");
- post_paused = TRUE;
- post_async_done = TRUE;
- basesink->priv->committed = TRUE;
- post_pending = GST_STATE_VOID_PENDING;
- break;
- case GST_STATE_READY:
- case GST_STATE_NULL:
- goto stopping;
- case GST_STATE_VOID_PENDING:
- goto nothing_pending;
- default:
- break;
- }
-
- /* we can report latency queries now */
- basesink->priv->have_latency = TRUE;
-
- GST_STATE (basesink) = pending;
- GST_STATE_NEXT (basesink) = GST_STATE_VOID_PENDING;
- GST_STATE_PENDING (basesink) = GST_STATE_VOID_PENDING;
- GST_STATE_RETURN (basesink) = GST_STATE_CHANGE_SUCCESS;
- GST_OBJECT_UNLOCK (basesink);
-
- if (post_paused) {
- GST_DEBUG_OBJECT (basesink, "posting PAUSED state change message");
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_state_changed (GST_OBJECT_CAST (basesink),
- current, next, post_pending));
- }
- if (post_async_done) {
- GST_DEBUG_OBJECT (basesink, "posting async-done message");
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_done (GST_OBJECT_CAST (basesink),
- GST_CLOCK_TIME_NONE));
- }
- if (post_playing) {
- if (post_paused) {
- GstElementClass *klass;
-
- klass = GST_ELEMENT_GET_CLASS (basesink);
- basesink->have_preroll = TRUE;
- /* after releasing this lock, the state change function
- * can execute concurrently with this thread. There is nothing we do to
- * prevent this for now. subclasses should be prepared to handle it. */
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
-
- if (klass->change_state)
- klass->change_state (GST_ELEMENT_CAST (basesink),
- GST_STATE_CHANGE_PAUSED_TO_PLAYING);
-
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- /* state change function could have been executed and we could be
- * flushing now */
- if (G_UNLIKELY (basesink->flushing))
- goto stopping_unlocked;
- }
- GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message");
- /* FIXME, we released the PREROLL lock above, it's possible that this
- * message is not correct anymore when the element went back to PAUSED */
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_state_changed (GST_OBJECT_CAST (basesink),
- next, pending, GST_STATE_VOID_PENDING));
- }
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_latency (GST_OBJECT_CAST (basesink)));
-
- GST_STATE_BROADCAST (basesink);
-
- return TRUE;
-
-nothing_pending:
- {
- /* Depending on the state, set our vars. We get in this situation when the
- * state change function got a change to update the state vars before the
- * streaming thread did. This is fine but we need to make sure that we
- * update the need_preroll var since it was %TRUE when we got here and might
- * become %FALSE if we got to PLAYING. */
- GST_DEBUG_OBJECT (basesink, "nothing to commit, now in %s",
- gst_element_state_get_name (current));
- switch (current) {
- case GST_STATE_PLAYING:
- basesink->need_preroll = FALSE;
- break;
- case GST_STATE_PAUSED:
- basesink->need_preroll = TRUE;
- break;
- default:
- basesink->need_preroll = FALSE;
- basesink->flushing = TRUE;
- break;
- }
- /* we can report latency queries now */
- basesink->priv->have_latency = TRUE;
- GST_OBJECT_UNLOCK (basesink);
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_latency (GST_OBJECT_CAST (basesink)));
- return TRUE;
- }
-stopping_unlocked:
- {
- GST_OBJECT_LOCK (basesink);
- goto stopping;
- }
-stopping:
- {
- /* app is going to READY */
- GST_DEBUG_OBJECT (basesink, "stopping");
- basesink->need_preroll = FALSE;
- basesink->flushing = TRUE;
- GST_OBJECT_UNLOCK (basesink);
- return FALSE;
- }
-}
-
-static void
-start_stepping (GstBaseSink * sink, GstSegment * segment,
- GstStepInfo * pending, GstStepInfo * current)
-{
- gint64 end;
- GstMessage *message;
-
- GST_DEBUG_OBJECT (sink, "update pending step");
-
- GST_OBJECT_LOCK (sink);
- memcpy (current, pending, sizeof (GstStepInfo));
- pending->valid = FALSE;
- GST_OBJECT_UNLOCK (sink);
-
- /* post message first */
- message =
- gst_message_new_step_start (GST_OBJECT (sink), TRUE, current->format,
- current->amount, current->rate, current->flush, current->intermediate);
- gst_message_set_seqnum (message, current->seqnum);
- gst_element_post_message (GST_ELEMENT (sink), message);
-
- /* get the running time of where we paused and remember it */
- current->start = gst_element_get_start_time (GST_ELEMENT_CAST (sink));
- gst_segment_set_running_time (segment, GST_FORMAT_TIME, current->start);
-
- /* set the new rate for the remainder of the segment */
- current->start_rate = segment->rate;
- segment->rate *= current->rate;
-
- /* save values */
- if (segment->rate > 0.0)
- current->start_stop = segment->stop;
- else
- current->start_start = segment->start;
-
- if (current->format == GST_FORMAT_TIME) {
- /* calculate the running-time when the step operation should stop */
- if (current->amount != -1)
- end = current->start + current->amount;
- else
- end = -1;
-
- if (!current->flush) {
- gint64 position;
-
- /* update the segment clipping regions for non-flushing seeks */
- if (segment->rate > 0.0) {
- if (end != -1)
- position =
- gst_segment_position_from_running_time (segment, GST_FORMAT_TIME,
- end);
- else
- position = segment->stop;
-
- segment->stop = position;
- segment->position = position;
- } else {
- if (end != -1)
- position =
- gst_segment_position_from_running_time (segment, GST_FORMAT_TIME,
- end);
- else
- position = segment->start;
-
- segment->time = position;
- segment->start = position;
- segment->position = position;
- }
- }
- }
-
- GST_DEBUG_OBJECT (sink, "segment now %" GST_SEGMENT_FORMAT, segment);
- GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (current->start));
-
- GST_DEBUG_OBJECT (sink, "step amount: %" G_GUINT64_FORMAT ", format: %s, "
- "rate: %f", current->amount, gst_format_get_name (current->format),
- current->rate);
-}
-
-static void
-stop_stepping (GstBaseSink * sink, GstSegment * segment,
- GstStepInfo * current, gint64 rstart, gint64 rstop, gboolean eos)
-{
- gint64 stop, position;
- GstMessage *message;
-
- GST_DEBUG_OBJECT (sink, "step complete");
-
- if (segment->rate > 0.0)
- stop = rstart;
- else
- stop = rstop;
-
- GST_DEBUG_OBJECT (sink,
- "step stop at running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (stop));
-
- if (stop == -1)
- current->duration = current->position;
- else
- current->duration = stop - current->start;
-
- GST_DEBUG_OBJECT (sink, "step elapsed running_time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (current->duration));
-
- position = current->start + current->duration;
-
- /* now move the segment to the new running time */
- gst_segment_set_running_time (segment, GST_FORMAT_TIME, position);
-
- if (current->flush) {
- /* and remove the time we flushed, start time did not change */
- segment->base = current->start;
- } else {
- /* start time is now the stepped position */
- gst_element_set_start_time (GST_ELEMENT_CAST (sink), position);
- }
-
- /* restore the previous rate */
- segment->rate = current->start_rate;
-
- if (segment->rate > 0.0)
- segment->stop = current->start_stop;
- else
- segment->start = current->start_start;
-
- /* post the step done when we know the stepped duration in TIME */
- message =
- gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format,
- current->amount, current->rate, current->flush, current->intermediate,
- current->duration, eos);
- gst_message_set_seqnum (message, current->seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (sink), message);
-
- if (!current->intermediate)
- sink->need_preroll = current->need_preroll;
-
- /* and the current step info finished and becomes invalid */
- current->valid = FALSE;
-}
-
-static gboolean
-handle_stepping (GstBaseSink * sink, GstSegment * segment,
- GstStepInfo * current, guint64 * cstart, guint64 * cstop, guint64 * rstart,
- guint64 * rstop)
-{
- gboolean step_end = FALSE;
-
- /* stepping never stops */
- if (current->amount == -1)
- return FALSE;
-
- /* see if we need to skip this buffer because of stepping */
- switch (current->format) {
- case GST_FORMAT_TIME:
- {
- guint64 end;
- guint64 first, last;
- gdouble abs_rate;
-
- if (segment->rate > 0.0) {
- if (segment->stop == *cstop)
- *rstop = *rstart + current->amount;
-
- first = *rstart;
- last = *rstop;
- } else {
- if (segment->start == *cstart)
- *rstart = *rstop + current->amount;
-
- first = *rstop;
- last = *rstart;
- }
-
- end = current->start + current->amount;
- current->position = first - current->start;
-
- abs_rate = ABS (segment->rate);
- if (G_UNLIKELY (abs_rate != 1.0))
- current->position /= abs_rate;
-
- GST_DEBUG_OBJECT (sink,
- "buffer: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
- GST_TIME_ARGS (first), GST_TIME_ARGS (last));
- GST_DEBUG_OBJECT (sink,
- "got time step %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "/%"
- GST_TIME_FORMAT, GST_TIME_ARGS (current->position),
- GST_TIME_ARGS (last - current->start),
- GST_TIME_ARGS (current->amount));
-
- if ((current->flush && current->position >= current->amount)
- || last >= end) {
- GST_DEBUG_OBJECT (sink, "step ended, we need clipping");
- step_end = TRUE;
- if (segment->rate > 0.0) {
- *rstart = end;
- *cstart =
- gst_segment_position_from_running_time (segment, GST_FORMAT_TIME,
- end);
- } else {
- *rstop = end;
- *cstop =
- gst_segment_position_from_running_time (segment, GST_FORMAT_TIME,
- end);
- }
- }
- GST_DEBUG_OBJECT (sink,
- "cstart %" GST_TIME_FORMAT ", rstart %" GST_TIME_FORMAT,
- GST_TIME_ARGS (*cstart), GST_TIME_ARGS (*rstart));
- GST_DEBUG_OBJECT (sink,
- "cstop %" GST_TIME_FORMAT ", rstop %" GST_TIME_FORMAT,
- GST_TIME_ARGS (*cstop), GST_TIME_ARGS (*rstop));
- break;
- }
- case GST_FORMAT_BUFFERS:
- GST_DEBUG_OBJECT (sink,
- "got default step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
- current->position, current->amount);
-
- if (current->position < current->amount) {
- current->position++;
- } else {
- step_end = TRUE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- default:
- GST_DEBUG_OBJECT (sink,
- "got unknown step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
- current->position, current->amount);
- break;
- }
- return step_end;
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Returns %TRUE if the object needs synchronisation and takes therefore
- * part in prerolling.
- *
- * rsstart/rsstop contain the start/stop in stream time.
- * rrstart/rrstop contain the start/stop in running time.
- */
-static gboolean
-gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
- GstClockTime * rsstart, GstClockTime * rsstop,
- GstClockTime * rrstart, GstClockTime * rrstop, GstClockTime * rrnext,
- gboolean * do_sync, gboolean * stepped, GstStepInfo * step,
- gboolean * step_end)
-{
- GstBaseSinkClass *bclass;
- GstClockTime start, stop; /* raw start/stop timestamps */
- guint64 cstart, cstop; /* clipped raw timestamps */
- guint64 rstart, rstop, rnext; /* clipped timestamps converted to running time */
- GstClockTime sstart, sstop; /* clipped timestamps converted to stream time */
- GstFormat format;
- GstBaseSinkPrivate *priv;
- GstSegment *segment;
- gboolean eos;
-
- priv = basesink->priv;
- segment = &basesink->segment;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
-again:
- /* start with nothing */
- start = stop = GST_CLOCK_TIME_NONE;
- eos = FALSE;
-
- if (G_UNLIKELY (GST_IS_EVENT (obj))) {
- GstEvent *event = GST_EVENT_CAST (obj);
-
- switch (GST_EVENT_TYPE (event)) {
- /* EOS event needs syncing */
- case GST_EVENT_EOS:
- {
- if (segment->rate >= 0.0) {
- sstart = sstop = priv->current_sstop;
- if (!GST_CLOCK_TIME_IS_VALID (sstart)) {
- /* we have not seen a buffer yet, use the segment values */
- sstart = sstop = gst_segment_to_stream_time (segment,
- segment->format, segment->stop);
- }
- } else {
- sstart = sstop = priv->current_sstart;
- if (!GST_CLOCK_TIME_IS_VALID (sstart)) {
- /* we have not seen a buffer yet, use the segment values */
- sstart = sstop = gst_segment_to_stream_time (segment,
- segment->format, segment->start);
- }
- }
-
- rstart = rstop = rnext = priv->eos_rtime;
- *do_sync = GST_CLOCK_TIME_IS_VALID (rstart);
- GST_DEBUG_OBJECT (basesink, "sync times for EOS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (rstart));
- /* if we are stepping, we end now */
- *step_end = step->valid;
- eos = TRUE;
- goto eos_done;
- }
- case GST_EVENT_GAP:
- {
- GstClockTime timestamp, duration;
- gst_event_parse_gap (event, &timestamp, &duration);
-
- GST_DEBUG_OBJECT (basesink, "Got Gap time %" GST_TIME_FORMAT
- " duration %" GST_TIME_FORMAT,
- GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
-
- if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
- start = timestamp;
- if (GST_CLOCK_TIME_IS_VALID (duration))
- stop = start + duration;
- }
- *do_sync = TRUE;
- break;
- }
- default:
- /* other events do not need syncing */
- return FALSE;
- }
- } else {
- /* else do buffer sync code */
- GstBuffer *buffer = GST_BUFFER_CAST (obj);
-
- /* just get the times to see if we need syncing, if the retuned start is -1
- * we don't sync. */
- if (bclass->get_times)
- bclass->get_times (basesink, buffer, &start, &stop);
-
- if (!GST_CLOCK_TIME_IS_VALID (start)) {
- /* we don't need to sync but we still want to get the timestamps for
- * tracking the position */
- gst_base_sink_default_get_times (basesink, buffer, &start, &stop);
- *do_sync = FALSE;
- } else {
- *do_sync = TRUE;
- }
- }
-
- GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
- ", stop: %" GST_TIME_FORMAT ", do_sync %d", GST_TIME_ARGS (start),
- GST_TIME_ARGS (stop), *do_sync);
-
- /* collect segment and format for code clarity */
- format = segment->format;
-
- /* clip */
- if (G_UNLIKELY (!gst_segment_clip (segment, format,
- start, stop, &cstart, &cstop))) {
- if (step->valid) {
- GST_DEBUG_OBJECT (basesink, "step out of segment");
- /* when we are stepping, pretend we're at the end of the segment */
- if (segment->rate > 0.0) {
- cstart = segment->stop;
- cstop = segment->stop;
- } else {
- cstart = segment->start;
- cstop = segment->start;
- }
- goto do_times;
- }
- goto out_of_segment;
- }
-
- if (G_UNLIKELY (start != cstart || stop != cstop)) {
- GST_DEBUG_OBJECT (basesink, "clipped to: start %" GST_TIME_FORMAT
- ", stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (cstart),
- GST_TIME_ARGS (cstop));
- }
-
- /* set last stop position */
- if (G_LIKELY (stop != GST_CLOCK_TIME_NONE && cstop != GST_CLOCK_TIME_NONE))
- segment->position = cstop;
- else
- segment->position = cstart;
-
-do_times:
- rstart = gst_segment_to_running_time (segment, format, cstart);
- rstop = gst_segment_to_running_time (segment, format, cstop);
-
- /* In reverse playback, play from stop to start */
- if (segment->rate < 0.0 && GST_CLOCK_TIME_IS_VALID (rstop)
- /* FIXME: Current stepping implemenation expects unmodified rstart/rstop
- * for reverse playback. Don't swap those values when stepping
- * unless stepping code is updated as such */
- && !step->valid) {
- GstClockTime tmp = rstart;
- rstart = rstop;
- rstop = tmp;
- }
-
- if (GST_CLOCK_TIME_IS_VALID (stop))
- rnext = rstop;
- else
- rnext = rstart;
-
- if (G_UNLIKELY (step->valid)) {
- if (!(*step_end = handle_stepping (basesink, segment, step, &cstart, &cstop,
- &rstart, &rstop))) {
- /* step is still busy, we discard data when we are flushing */
- *stepped = step->flush;
- GST_DEBUG_OBJECT (basesink, "stepping busy");
- }
- }
- /* this can produce wrong values if we accumulated non-TIME segments. If this happens,
- * upstream is behaving very badly */
- sstart = gst_segment_to_stream_time (segment, format, cstart);
- sstop = gst_segment_to_stream_time (segment, format, cstop);
-
-eos_done:
- /* eos_done label only called when doing EOS, we also stop stepping then */
- if (*step_end && step->flush) {
- GST_DEBUG_OBJECT (basesink, "flushing step ended");
- stop_stepping (basesink, segment, step, rstart, rstop, eos);
- *step_end = FALSE;
- /* re-determine running start times for adjusted segment
- * (which has a flushed amount of running/accumulated time removed) */
- if (!GST_IS_EVENT (obj)) {
- GST_DEBUG_OBJECT (basesink, "refresh sync times");
- goto again;
- }
- }
-
- /* save times */
- *rsstart = sstart;
- *rsstop = sstop;
- *rrstart = rstart;
- *rrstop = rstop;
- *rrnext = rnext;
-
- /* buffers and EOS always need syncing and preroll */
- return TRUE;
-
- /* special cases */
-out_of_segment:
- {
- /* we usually clip in the chain function already but stepping could cause
- * the segment to be updated later. we return %FALSE so that we don't try
- * to sync on it. */
- GST_LOG_OBJECT (basesink, "buffer skipped, not in segment");
- return FALSE;
- }
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK, LOCK
- * adjust a timestamp with the latency and timestamp offset. This function does
- * not adjust for the render delay. */
-static GstClockTime
-gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time)
-{
- GstClockTimeDiff ts_offset;
-
- /* don't do anything funny with invalid timestamps */
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time)))
- return time;
-
- time += basesink->priv->latency;
-
- /* apply offset, be careful for underflows */
- ts_offset = basesink->priv->ts_offset;
- if (ts_offset < 0) {
- ts_offset = -ts_offset;
- if (ts_offset < time)
- time -= ts_offset;
- else
- time = 0;
- } else
- time += ts_offset;
-
- /* subtract the render delay again, which was included in the latency */
- if (time > basesink->priv->render_delay)
- time -= basesink->priv->render_delay;
- else
- time = 0;
-
- return time;
-}
-
-/**
- * gst_base_sink_wait_clock:
- * @sink: the sink
- * @time: the running_time to be reached
- * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL
- *
- * This function will block until @time is reached. It is usually called by
- * subclasses that use their own internal synchronisation.
- *
- * If @time is not valid, no synchronisation is done and %GST_CLOCK_BADTIME is
- * returned. Likewise, if synchronisation is disabled in the element or there
- * is no clock, no synchronisation is done and %GST_CLOCK_BADTIME is returned.
- *
- * This function should only be called with the PREROLL_LOCK held, like when
- * receiving an EOS event in the #GstBaseSinkClass::event vmethod or when
- * receiving a buffer in
- * the #GstBaseSinkClass::render vmethod.
- *
- * The @time argument should be the running_time of when this method should
- * return and is not adjusted with any latency or offset configured in the
- * sink.
- *
- * Returns: #GstClockReturn
- */
-GstClockReturn
-gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
- GstClockTimeDiff * jitter)
-{
- GstClockReturn ret;
- GstClock *clock;
- GstClockTime base_time;
-
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time)))
- goto invalid_time;
-
- GST_OBJECT_LOCK (sink);
- if (G_UNLIKELY (!sink->sync))
- goto no_sync;
-
- if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (sink)) == NULL))
- goto no_clock;
-
- base_time = GST_ELEMENT_CAST (sink)->base_time;
- GST_LOG_OBJECT (sink,
- "time %" GST_TIME_FORMAT ", base_time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (time), GST_TIME_ARGS (base_time));
-
- /* add base_time to running_time to get the time against the clock */
- time += base_time;
-
- /* Re-use existing clockid if available */
- if (G_LIKELY (sink->priv->cached_clock_id != NULL
- && gst_clock_id_uses_clock (sink->priv->cached_clock_id, clock))) {
- if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
- time)) {
- gst_clock_id_unref (sink->priv->cached_clock_id);
- sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
- }
- } else {
- if (sink->priv->cached_clock_id != NULL)
- gst_clock_id_unref (sink->priv->cached_clock_id);
- sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
- }
- GST_OBJECT_UNLOCK (sink);
-
- /* A blocking wait is performed on the clock. We save the ClockID
- * so we can unlock the entry at any time. While we are blocking, we
- * release the PREROLL_LOCK so that other threads can interrupt the
- * entry. */
- sink->clock_id = sink->priv->cached_clock_id;
- /* release the preroll lock while waiting */
- GST_BASE_SINK_PREROLL_UNLOCK (sink);
-
- ret = gst_clock_id_wait (sink->priv->cached_clock_id, jitter);
-
- GST_BASE_SINK_PREROLL_LOCK (sink);
- sink->clock_id = NULL;
-
- return ret;
-
- /* no syncing needed */
-invalid_time:
- {
- GST_DEBUG_OBJECT (sink, "time not valid, no sync needed");
- return GST_CLOCK_BADTIME;
- }
-no_sync:
- {
- GST_DEBUG_OBJECT (sink, "sync disabled");
- GST_OBJECT_UNLOCK (sink);
- return GST_CLOCK_BADTIME;
- }
-no_clock:
- {
- GST_DEBUG_OBJECT (sink, "no clock, can't sync");
- GST_OBJECT_UNLOCK (sink);
- return GST_CLOCK_BADTIME;
- }
-}
-
-/**
- * gst_base_sink_wait_preroll:
- * @sink: the sink
- *
- * If the #GstBaseSinkClass::render method performs its own synchronisation
- * against the clock it must unblock when going from PLAYING to the PAUSED state
- * and call this method before continuing to render the remaining data.
- *
- * If the #GstBaseSinkClass::render method can block on something else than
- * the clock, it must also be ready to unblock immediately on
- * the #GstBaseSinkClass::unlock method and cause the
- * #GstBaseSinkClass::render method to immediately call this function.
- * In this case, the subclass must be prepared to continue rendering where it
- * left off if this function returns %GST_FLOW_OK.
- *
- * This function will block until a state change to PLAYING happens (in which
- * case this function returns %GST_FLOW_OK) or the processing must be stopped due
- * to a state change to READY or a FLUSH event (in which case this function
- * returns %GST_FLOW_FLUSHING).
- *
- * This function should only be called with the PREROLL_LOCK held, like in the
- * render function.
- *
- * Returns: %GST_FLOW_OK if the preroll completed and processing can
- * continue. Any other return value should be returned from the render vmethod.
- */
-GstFlowReturn
-gst_base_sink_wait_preroll (GstBaseSink * sink)
-{
- sink->have_preroll = TRUE;
- GST_DEBUG_OBJECT (sink, "waiting in preroll for flush or PLAYING");
- /* block until the state changes, or we get a flush, or something */
- GST_BASE_SINK_PREROLL_WAIT (sink);
- sink->have_preroll = FALSE;
- if (G_UNLIKELY (sink->flushing))
- goto stopping;
- if (G_UNLIKELY (sink->priv->step_unlock))
- goto step_unlocked;
- GST_DEBUG_OBJECT (sink, "continue after preroll");
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-stopping:
- {
- GST_DEBUG_OBJECT (sink, "preroll interrupted because of flush");
- return GST_FLOW_FLUSHING;
- }
-step_unlocked:
- {
- sink->priv->step_unlock = FALSE;
- GST_DEBUG_OBJECT (sink, "preroll interrupted because of step");
- return GST_FLOW_STEP;
- }
-}
-
-/**
- * gst_base_sink_do_preroll:
- * @sink: the sink
- * @obj: (transfer none): the mini object that caused the preroll
- *
- * If the @sink spawns its own thread for pulling buffers from upstream it
- * should call this method after it has pulled a buffer. If the element needed
- * to preroll, this function will perform the preroll and will then block
- * until the element state is changed.
- *
- * This function should be called with the PREROLL_LOCK held.
- *
- * Returns: %GST_FLOW_OK if the preroll completed and processing can
- * continue. Any other return value should be returned from the render vmethod.
- */
-GstFlowReturn
-gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
-{
- GstFlowReturn ret;
-
- while (G_UNLIKELY (sink->need_preroll)) {
- GST_DEBUG_OBJECT (sink, "prerolling object %p", obj);
-
- /* if it's a buffer, we need to call the preroll method */
- if (sink->priv->call_preroll) {
- GstBaseSinkClass *bclass;
- GstBuffer *buf;
-
- if (GST_IS_BUFFER_LIST (obj)) {
- buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0);
- gst_base_sink_set_last_buffer (sink, buf);
- gst_base_sink_set_last_buffer_list (sink, GST_BUFFER_LIST_CAST (obj));
- g_assert (NULL != buf);
- } else if (GST_IS_BUFFER (obj)) {
- buf = GST_BUFFER_CAST (obj);
- /* For buffer lists do not set last buffer for now */
- gst_base_sink_set_last_buffer (sink, buf);
- gst_base_sink_set_last_buffer_list (sink, NULL);
- } else {
- buf = NULL;
- }
-
- if (buf) {
- GST_DEBUG_OBJECT (sink, "preroll buffer %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
- bclass = GST_BASE_SINK_GET_CLASS (sink);
-
- if (bclass->prepare)
- if ((ret = bclass->prepare (sink, buf)) != GST_FLOW_OK)
- goto prepare_canceled;
-
- if (bclass->preroll)
- if ((ret = bclass->preroll (sink, buf)) != GST_FLOW_OK)
- goto preroll_canceled;
-
- sink->priv->call_preroll = FALSE;
- }
- }
-
- /* commit state */
- if (G_LIKELY (sink->playing_async)) {
- if (G_UNLIKELY (!gst_base_sink_commit_state (sink)))
- goto stopping;
- }
-
- /* need to recheck here because the commit state could have
- * made us not need the preroll anymore */
- if (G_LIKELY (sink->need_preroll)) {
- /* block until the state changes, or we get a flush, or something */
- ret = gst_base_sink_wait_preroll (sink);
- if ((ret != GST_FLOW_OK) && (ret != GST_FLOW_STEP))
- goto preroll_failed;
- }
- }
- return GST_FLOW_OK;
-
- /* ERRORS */
-prepare_canceled:
- {
- GST_DEBUG_OBJECT (sink, "prepare failed, abort state");
- gst_element_abort_state (GST_ELEMENT_CAST (sink));
- return ret;
- }
-preroll_canceled:
- {
- GST_DEBUG_OBJECT (sink, "preroll failed, abort state");
- gst_element_abort_state (GST_ELEMENT_CAST (sink));
- return ret;
- }
-stopping:
- {
- GST_DEBUG_OBJECT (sink, "stopping while committing state");
- return GST_FLOW_FLUSHING;
- }
-preroll_failed:
- {
- GST_DEBUG_OBJECT (sink, "preroll failed: %s", gst_flow_get_name (ret));
- return ret;
- }
-}
-
-/**
- * gst_base_sink_wait:
- * @sink: the sink
- * @time: the running_time to be reached
- * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL
- *
- * This function will wait for preroll to complete and will then block until @time
- * is reached. It is usually called by subclasses that use their own internal
- * synchronisation but want to let some synchronization (like EOS) be handled
- * by the base class.
- *
- * This function should only be called with the PREROLL_LOCK held (like when
- * receiving an EOS event in the ::event vmethod or when handling buffers in
- * ::render).
- *
- * The @time argument should be the running_time of when the timeout should happen
- * and will be adjusted with any latency and offset configured in the sink.
- *
- * Returns: #GstFlowReturn
- */
-GstFlowReturn
-gst_base_sink_wait (GstBaseSink * sink, GstClockTime time,
- GstClockTimeDiff * jitter)
-{
- GstClockReturn status;
- GstFlowReturn ret;
-
- do {
- GstClockTime stime;
-
- GST_DEBUG_OBJECT (sink, "checking preroll");
-
- /* first wait for the playing state before we can continue */
- while (G_UNLIKELY (sink->need_preroll)) {
- ret = gst_base_sink_wait_preroll (sink);
- if ((ret != GST_FLOW_OK) && (ret != GST_FLOW_STEP))
- goto flushing;
- }
-
- /* preroll done, we can sync since we are in PLAYING now. */
- GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"
- GST_TIME_FORMAT, GST_TIME_ARGS (time));
-
- /* compensate for latency, ts_offset and render delay */
- stime = gst_base_sink_adjust_time (sink, time);
-
- /* wait for the clock, this can be interrupted because we got shut down or
- * we PAUSED. */
- status = gst_base_sink_wait_clock (sink, stime, jitter);
-
- GST_DEBUG_OBJECT (sink, "clock returned %d", status);
-
- /* invalid time, no clock or sync disabled, just continue then */
- if (status == GST_CLOCK_BADTIME)
- break;
-
- /* waiting could have been interrupted and we can be flushing now */
- if (G_UNLIKELY (sink->flushing))
- goto flushing;
-
- /* retry if we got unscheduled, which means we did not reach the timeout
- * yet. if some other error occurs, we continue. */
- } while (status == GST_CLOCK_UNSCHEDULED);
-
- GST_DEBUG_OBJECT (sink, "end of stream");
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (sink, "we are flushing");
- return GST_FLOW_FLUSHING;
- }
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Make sure we are in PLAYING and synchronize an object to the clock.
- *
- * If we need preroll, we are not in PLAYING. We try to commit the state
- * if needed and then block if we still are not PLAYING.
- *
- * We start waiting on the clock in PLAYING. If we got interrupted, we
- * immediately try to re-preroll.
- *
- * Some objects do not need synchronisation (most events) and so this function
- * immediately returns GST_FLOW_OK.
- *
- * for objects that arrive later than max-lateness to be synchronized to the
- * clock have the @late boolean set to %TRUE.
- *
- * This function keeps a running average of the jitter (the diff between the
- * clock time and the requested sync time). The jitter is negative for
- * objects that arrive in time and positive for late buffers.
- *
- * does not take ownership of obj.
- */
-static GstFlowReturn
-gst_base_sink_do_sync (GstBaseSink * basesink,
- GstMiniObject * obj, gboolean * late, gboolean * step_end)
-{
- GstClockTimeDiff jitter = 0;
- gboolean syncable;
- GstClockReturn status = GST_CLOCK_OK;
- GstClockTime rstart, rstop, rnext, sstart, sstop, stime;
- gboolean do_sync;
- GstBaseSinkPrivate *priv;
- GstFlowReturn ret;
- GstStepInfo *current, *pending;
- gboolean stepped;
- guint32 current_instant_rate_seqnum;
-
- priv = basesink->priv;
-
- /* remember the currently handled instant-rate sequence number. If this
- * changes after pre-rolling, we need to goto do_step again for updating
- * the timing information of the current buffer */
- current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
-do_step:
- sstart = sstop = rstart = rstop = rnext = GST_CLOCK_TIME_NONE;
- do_sync = TRUE;
- stepped = FALSE;
-
- priv->current_rstart = GST_CLOCK_TIME_NONE;
-
- /* get stepping info */
- current = &priv->current_step;
- pending = &priv->pending_step;
-
- /* get timing information for this object against the render segment */
- syncable = gst_base_sink_get_sync_times (basesink, obj,
- &sstart, &sstop, &rstart, &rstop, &rnext, &do_sync, &stepped, current,
- step_end);
-
- if (G_UNLIKELY (stepped))
- goto step_skipped;
-
- /* a syncable object needs to participate in preroll and
- * clocking. All buffers and EOS are syncable. */
- if (G_UNLIKELY (!syncable))
- goto not_syncable;
-
- /* store timing info for current object */
- priv->current_rstart = rstart;
- priv->current_rstop = (GST_CLOCK_TIME_IS_VALID (rstop) ? rstop : rstart);
-
- /* save sync time for eos when the previous object needed sync */
- priv->eos_rtime = (do_sync ? rnext : GST_CLOCK_TIME_NONE);
-
- /* calculate inter frame spacing */
- if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (priv->prev_rstart) &&
- priv->prev_rstart < rstart)) {
- GstClockTime in_diff;
-
- in_diff = rstart - priv->prev_rstart;
-
- if (priv->avg_in_diff == -1)
- priv->avg_in_diff = in_diff;
- else
- priv->avg_in_diff = UPDATE_RUNNING_AVG (priv->avg_in_diff, in_diff);
-
- GST_LOG_OBJECT (basesink, "avg frame diff %" GST_TIME_FORMAT,
- GST_TIME_ARGS (priv->avg_in_diff));
-
- }
- priv->prev_rstart = rstart;
-
- if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (priv->earliest_in_time) &&
- rstart < priv->earliest_in_time))
- goto qos_dropped;
-
-again:
- /* first do preroll, this makes sure we commit our state
- * to PAUSED and can continue to PLAYING. We cannot perform
- * any clock sync in PAUSED because there is no clock. */
- ret = gst_base_sink_do_preroll (basesink, obj);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto preroll_failed;
-
- /* update the segment with a pending step if the current one is invalid and we
- * have a new pending one. We only accept new step updates after a preroll */
- if (G_UNLIKELY (pending->valid && !current->valid)) {
- start_stepping (basesink, &basesink->segment, pending, current);
- goto do_step;
- }
-
- if (G_UNLIKELY (priv->instant_rate_sync_seqnum !=
- current_instant_rate_seqnum)) {
- current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
- // TODO rename the goto label - it does more these days.
- goto do_step;
- }
-
- /* After rendering we store the position of the last buffer so that we can use
- * it to report the position. We need to take the lock here. */
- GST_OBJECT_LOCK (basesink);
- priv->current_sstart = sstart;
- priv->current_sstop = (GST_CLOCK_TIME_IS_VALID (sstop) ? sstop : sstart);
- GST_OBJECT_UNLOCK (basesink);
-
- if (!do_sync)
- goto done;
-
- /* adjust for latency */
- stime = gst_base_sink_adjust_time (basesink, rstart);
-
- /* adjust for rate control */
- if (priv->rc_next == -1 || (stime != -1 && stime >= priv->rc_next)) {
- GST_DEBUG_OBJECT (basesink, "reset rc_time to time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (stime));
- priv->rc_time = stime;
- priv->rc_accumulated = 0;
- } else {
- GST_DEBUG_OBJECT (basesink, "rate control next %" GST_TIME_FORMAT,
- GST_TIME_ARGS (priv->rc_next));
- stime = priv->rc_next;
- }
-
- /* preroll done, we can sync since we are in PLAYING now. */
- GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %"
- GST_TIME_FORMAT ", adjusted %" GST_TIME_FORMAT,
- GST_TIME_ARGS (rstart), GST_TIME_ARGS (stime));
-
- /* This function will return immediately if start == -1, no clock
- * or sync is disabled with GST_CLOCK_BADTIME. */
- status = gst_base_sink_wait_clock (basesink, stime, &jitter);
-
- GST_DEBUG_OBJECT (basesink, "clock returned %d, jitter %c%" GST_TIME_FORMAT,
- status, (jitter < 0 ? '-' : ' '), GST_TIME_ARGS (ABS (jitter)));
-
- /* invalid time, no clock or sync disabled, just render */
- if (status == GST_CLOCK_BADTIME)
- goto done;
-
- /* waiting could have been interrupted and we can be flushing now */
- if (G_UNLIKELY (basesink->flushing))
- goto flushing;
-
- /* check for unlocked by a state change, we are not flushing so
- * we can try to preroll on the current buffer. */
- if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
- if (G_UNLIKELY (priv->instant_rate_sync_seqnum !=
- current_instant_rate_seqnum)) {
- current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
- // TODO rename
- goto do_step;
- }
-
- GST_DEBUG_OBJECT (basesink, "unscheduled, waiting some more");
- priv->call_preroll = TRUE;
- goto again;
- }
-
- /* successful syncing done, record observation */
- priv->current_jitter = jitter;
-
- /* check if the object should be dropped */
- *late = gst_base_sink_is_too_late (basesink, obj, rstart, rstop,
- status, jitter, TRUE);
-
-done:
- return GST_FLOW_OK;
-
- /* ERRORS */
-step_skipped:
- {
- GST_DEBUG_OBJECT (basesink, "skipped stepped object %p", obj);
- *late = TRUE;
- return GST_FLOW_OK;
- }
-not_syncable:
- {
- GST_DEBUG_OBJECT (basesink, "non syncable object %p", obj);
- return GST_FLOW_OK;
- }
-qos_dropped:
- {
- GST_DEBUG_OBJECT (basesink, "dropped because of QoS %p", obj);
- *late = TRUE;
- return GST_FLOW_OK;
- }
-flushing:
- {
- GST_DEBUG_OBJECT (basesink, "we are flushing");
- return GST_FLOW_FLUSHING;
- }
-preroll_failed:
- {
- GST_DEBUG_OBJECT (basesink, "preroll failed");
- *step_end = FALSE;
- return ret;
- }
-}
-
-static gboolean
-gst_base_sink_send_qos (GstBaseSink * basesink, GstQOSType type,
- gdouble proportion, GstClockTime time, GstClockTimeDiff diff)
-{
- GstEvent *event;
- gboolean res;
-
- /* generate Quality-of-Service event */
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
- "qos: type %d, proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
- GST_TIME_FORMAT, type, proportion, diff, GST_TIME_ARGS (time));
-
- /* Compensate for any instant-rate-change related running time offset
- * between upstream and the internal running time of the sink */
- if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
- GstClockTime actual_duration;
- GstClockTime upstream_duration;
- GstClockTimeDiff difference;
- gboolean negative_duration;
-
- GST_DEBUG_OBJECT (basesink,
- "Current internal running time %" GST_TIME_FORMAT
- ", last internal running time %" GST_TIME_FORMAT, GST_TIME_ARGS (time),
- GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
-
- /* Calculate how much running time was spent since the last switch/segment
- * in the "corrected upstream segment", our segment */
- /* Due to rounding errors and other inaccuracies, it can happen
- * that our calculated internal running time is before the upstream
- * running time. We need to compensate for that */
- if (time < basesink->priv->last_anchor_running_time) {
- actual_duration = basesink->priv->last_anchor_running_time - time;
- negative_duration = TRUE;
- } else {
- actual_duration = time - basesink->priv->last_anchor_running_time;
- negative_duration = FALSE;
- }
-
- /* Transpose that duration (i.e. what upstream beliefs) */
- upstream_duration =
- (actual_duration * basesink->segment.rate) /
- basesink->priv->upstream_segment.rate;
-
- /* Add the difference to the previously accumulated correction */
- if (negative_duration)
- difference = upstream_duration - actual_duration;
- else
- difference = actual_duration - upstream_duration;
-
- GST_DEBUG_OBJECT (basesink,
- "Current instant rate correction offset. Actual duration %"
- GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
- ", negative %d, difference %" GST_STIME_FORMAT ", current offset %"
- GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
- GST_TIME_ARGS (upstream_duration), negative_duration,
- GST_STIME_ARGS (difference),
- GST_STIME_ARGS (basesink->priv->instant_rate_offset + difference));
-
- difference = basesink->priv->instant_rate_offset + difference;
-
- if (difference > 0 && time < difference)
- time = 0;
- else
- time -= difference;
- }
-
- event = gst_event_new_qos (type, proportion, diff, time);
-
- /* send upstream */
- res = gst_pad_push_event (basesink->sinkpad, event);
-
- return res;
-}
-
-static void
-gst_base_sink_perform_qos (GstBaseSink * sink, gboolean dropped)
-{
- GstBaseSinkPrivate *priv;
- GstClockTime start, stop;
- GstClockTimeDiff jitter;
- GstClockTime pt, entered, left;
- GstClockTime duration;
- gdouble rate;
-
- priv = sink->priv;
-
- start = priv->current_rstart;
-
- if (priv->current_step.valid)
- return;
-
- /* if Quality-of-Service disabled, do nothing */
- if (!g_atomic_int_get (&priv->qos_enabled) ||
- !GST_CLOCK_TIME_IS_VALID (start))
- return;
-
- stop = priv->current_rstop;
- jitter = priv->current_jitter;
-
- if (jitter < 0) {
- /* this is the time the buffer entered the sink */
- if (start < -jitter)
- entered = 0;
- else
- entered = start + jitter;
- left = start;
- } else {
- /* this is the time the buffer entered the sink */
- entered = start + jitter;
- /* this is the time the buffer left the sink */
- left = start + jitter;
- }
-
- /* calculate duration of the buffer, only use buffer durations if not in
- * trick mode or key-unit mode. Otherwise the buffer durations will be
- * meaningless as frames are being dropped in-between without updating the
- * durations. */
- duration = priv->avg_in_diff;
-
- /* if we have the time when the last buffer left us, calculate
- * processing time */
- if (GST_CLOCK_TIME_IS_VALID (priv->last_left)) {
- if (entered > priv->last_left) {
- pt = entered - priv->last_left;
- } else {
- pt = 0;
- }
- } else {
- pt = priv->avg_pt;
- }
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, "start: %" GST_TIME_FORMAT
- ", stop %" GST_TIME_FORMAT ", entered %" GST_TIME_FORMAT ", left %"
- GST_TIME_FORMAT ", pt: %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
- ",jitter %" G_GINT64_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
- GST_TIME_ARGS (entered), GST_TIME_ARGS (left), GST_TIME_ARGS (pt),
- GST_TIME_ARGS (duration), jitter);
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink,
- "avg_pt: %" GST_TIME_FORMAT ", avg_rate: %g",
- GST_TIME_ARGS (priv->avg_pt), priv->avg_rate);
-
- /* collect running averages. for first observations, we copy the
- * values */
- if (!GST_CLOCK_TIME_IS_VALID (priv->avg_pt))
- priv->avg_pt = pt;
- else
- priv->avg_pt = UPDATE_RUNNING_AVG (priv->avg_pt, pt);
-
- if (duration != -1 && duration != 0) {
- rate =
- gst_guint64_to_gdouble (priv->avg_pt) /
- gst_guint64_to_gdouble (duration);
- } else {
- rate = 1.0;
- }
-
- if (GST_CLOCK_TIME_IS_VALID (priv->last_left)) {
- if (dropped || priv->avg_rate < 0.0) {
- priv->avg_rate = rate;
- } else {
- if (rate > 1.0)
- priv->avg_rate = UPDATE_RUNNING_AVG_N (priv->avg_rate, rate);
- else
- priv->avg_rate = UPDATE_RUNNING_AVG_P (priv->avg_rate, rate);
- }
- }
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink,
- "updated: avg_pt: %" GST_TIME_FORMAT
- ", avg_rate: %g", GST_TIME_ARGS (priv->avg_pt), priv->avg_rate);
-
-
- if (priv->avg_rate >= 0.0) {
- GstQOSType type;
- GstClockTimeDiff diff;
-
- /* if we have a valid rate, start sending QoS messages */
- if (priv->current_jitter < 0) {
- /* make sure we never go below 0 when adding the jitter to the
- * timestamp. */
- if (priv->current_rstart < -priv->current_jitter)
- priv->current_jitter = -priv->current_rstart;
- }
-
- if (priv->throttle_time > 0) {
- diff = priv->throttle_time;
- type = GST_QOS_TYPE_THROTTLE;
- } else {
- diff = priv->current_jitter;
- if (diff <= 0)
- type = GST_QOS_TYPE_OVERFLOW;
- else
- type = GST_QOS_TYPE_UNDERFLOW;
- }
-
- gst_base_sink_send_qos (sink, type, priv->avg_rate, priv->current_rstart,
- diff);
- }
-
- /* record when this buffer will leave us */
- priv->last_left = left;
-}
-
-/* reset all qos measuring */
-static void
-gst_base_sink_reset_qos (GstBaseSink * sink)
-{
- GstBaseSinkPrivate *priv;
-
- priv = sink->priv;
-
- priv->last_render_time = GST_CLOCK_TIME_NONE;
- priv->prev_rstart = GST_CLOCK_TIME_NONE;
- priv->earliest_in_time = GST_CLOCK_TIME_NONE;
- priv->last_left = GST_CLOCK_TIME_NONE;
- priv->avg_pt = GST_CLOCK_TIME_NONE;
- priv->avg_rate = -1.0;
- priv->avg_in_diff = GST_CLOCK_TIME_NONE;
- priv->rendered = 0;
- priv->dropped = 0;
-
-}
-
-/* Checks if the object was scheduled too late.
- *
- * rstart/rstop contain the running_time start and stop values
- * of the object.
- *
- * status and jitter contain the return values from the clock wait.
- *
- * returns %TRUE if the buffer was too late.
- */
-static gboolean
-gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
- GstClockTime rstart, GstClockTime rstop,
- GstClockReturn status, GstClockTimeDiff jitter, gboolean render)
-{
- gboolean late;
- guint64 max_lateness;
- GstBaseSinkPrivate *priv;
-
- priv = basesink->priv;
-
- late = FALSE;
-
- /* only for objects that were too late */
- if (G_LIKELY (status != GST_CLOCK_EARLY))
- goto in_time;
-
- max_lateness = basesink->max_lateness;
-
- /* check if frame dropping is enabled */
- if (max_lateness == -1)
- goto no_drop;
-
- /* only check for buffers */
- if (G_UNLIKELY (!GST_IS_BUFFER (obj)))
- goto not_buffer;
-
- /* can't do check if we don't have a timestamp */
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (rstart)))
- goto no_timestamp;
-
- /* we can add a valid stop time */
- if (GST_CLOCK_TIME_IS_VALID (rstop))
- max_lateness += rstop;
- else {
- max_lateness += rstart;
- /* no stop time, use avg frame diff */
- if (priv->avg_in_diff != -1)
- max_lateness += priv->avg_in_diff;
- }
-
- /* if the jitter bigger than duration and lateness we are too late */
- if ((late = rstart + jitter > max_lateness)) {
- GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink,
- "buffer is too late %" GST_TIME_FORMAT
- " > %" GST_TIME_FORMAT, GST_TIME_ARGS (rstart + jitter),
- GST_TIME_ARGS (max_lateness));
- /* !!emergency!!, if we did not receive anything valid for more than a
- * second, render it anyway so the user sees something */
- if (GST_CLOCK_TIME_IS_VALID (priv->last_render_time) &&
- rstart - priv->last_render_time > GST_SECOND) {
- late = FALSE;
- GST_ELEMENT_WARNING (basesink, CORE, CLOCK,
- (_("A lot of buffers are being dropped.")),
- ("There may be a timestamping problem, or this computer is too slow."));
- GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink,
- "**emergency** last buffer at %" GST_TIME_FORMAT " > GST_SECOND",
- GST_TIME_ARGS (priv->last_render_time));
- }
- }
-
-done:
- if (render && (!late || !GST_CLOCK_TIME_IS_VALID (priv->last_render_time))) {
- priv->last_render_time = rstart;
- /* the next allowed input timestamp */
- if (priv->throttle_time > 0)
- priv->earliest_in_time = rstart + priv->throttle_time;
- }
- return late;
-
- /* all is fine */
-in_time:
- {
- GST_DEBUG_OBJECT (basesink, "object was scheduled in time");
- goto done;
- }
-no_drop:
- {
- GST_DEBUG_OBJECT (basesink, "frame dropping disabled");
- goto done;
- }
-not_buffer:
- {
- GST_DEBUG_OBJECT (basesink, "object is not a buffer");
- return FALSE;
- }
-no_timestamp:
- {
- GST_DEBUG_OBJECT (basesink, "buffer has no timestamp");
- return FALSE;
- }
-}
-
-static void
-gst_base_sink_update_start_time (GstBaseSink * basesink)
-{
- GstClock *clock;
-
- GST_OBJECT_LOCK (basesink);
- if (GST_STATE (basesink) == GST_STATE_PLAYING
- && (clock = GST_ELEMENT_CLOCK (basesink))) {
- GstClockTime now;
-
- gst_object_ref (clock);
- GST_OBJECT_UNLOCK (basesink);
-
- /* calculate the time when we stopped */
- now = gst_clock_get_time (clock);
- gst_object_unref (clock);
-
- GST_OBJECT_LOCK (basesink);
- /* store the current running time */
- if (GST_ELEMENT_START_TIME (basesink) != GST_CLOCK_TIME_NONE) {
- if (now != GST_CLOCK_TIME_NONE)
- GST_ELEMENT_START_TIME (basesink) =
- now - GST_ELEMENT_CAST (basesink)->base_time;
- else
- GST_WARNING_OBJECT (basesink,
- "Clock %s returned invalid time, can't calculate "
- "running_time when going to the PAUSED state",
- GST_OBJECT_NAME (clock));
- }
- GST_DEBUG_OBJECT (basesink,
- "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
- ", base_time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_ELEMENT_START_TIME (basesink)),
- GST_TIME_ARGS (now),
- GST_TIME_ARGS (GST_ELEMENT_CAST (basesink)->base_time));
- }
- GST_OBJECT_UNLOCK (basesink);
-}
-
-static void
-gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
-{
- /* make sure we are not blocked on the clock also clear any pending
- * eos state. */
- gst_base_sink_set_flushing (basesink, pad, TRUE);
-
- /* we grab the stream lock but that is not needed since setting the
- * sink to flushing would make sure no state commit is being done
- * anymore */
- GST_PAD_STREAM_LOCK (pad);
- gst_base_sink_reset_qos (basesink);
- /* and we need to commit our state again on the next
- * prerolled buffer */
- basesink->playing_async = TRUE;
- if (basesink->priv->async_enabled) {
- gst_base_sink_update_start_time (basesink);
- gst_element_lost_state (GST_ELEMENT_CAST (basesink));
- } else {
- /* start time reset in above case as well;
- * arranges for a.o. proper position reporting when flushing in PAUSED */
- gst_element_set_start_time (GST_ELEMENT_CAST (basesink), 0);
- basesink->priv->have_latency = TRUE;
- }
- gst_base_sink_set_last_buffer (basesink, NULL);
- gst_base_sink_set_last_buffer_list (basesink, NULL);
- GST_PAD_STREAM_UNLOCK (pad);
-}
-
-static void
-gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad,
- gboolean reset_time)
-{
- /* unset flushing so we can accept new data, this also flushes out any EOS
- * event. */
- gst_base_sink_set_flushing (basesink, pad, FALSE);
-
- /* for position reporting */
- GST_OBJECT_LOCK (basesink);
- basesink->priv->current_sstart = GST_CLOCK_TIME_NONE;
- basesink->priv->current_sstop = GST_CLOCK_TIME_NONE;
- basesink->priv->eos_rtime = GST_CLOCK_TIME_NONE;
- basesink->priv->call_preroll = TRUE;
- basesink->priv->current_step.valid = FALSE;
- basesink->priv->pending_step.valid = FALSE;
- if (basesink->pad_mode == GST_PAD_MODE_PUSH) {
- /* we need new segment info after the flush. */
- basesink->have_newsegment = FALSE;
- if (reset_time) {
- gst_segment_init (&basesink->priv->upstream_segment,
- GST_FORMAT_UNDEFINED);
- gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
- GST_ELEMENT_START_TIME (basesink) = 0;
-
- basesink->priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
- basesink->priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
- basesink->priv->instant_rate_multiplier = 0;
- basesink->priv->segment_seqnum = GST_SEQNUM_INVALID;
- basesink->priv->instant_rate_offset = 0;
- basesink->priv->last_anchor_running_time = 0;
- }
- }
- GST_OBJECT_UNLOCK (basesink);
-
- if (reset_time) {
- GST_DEBUG_OBJECT (basesink, "posting reset-time message");
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_reset_time (GST_OBJECT_CAST (basesink), 0));
- }
-}
-
-static GstFlowReturn
-gst_base_sink_default_wait_event (GstBaseSink * basesink, GstEvent * event)
-{
- GstFlowReturn ret;
- gboolean late, step_end = FALSE;
-
- ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (event),
- &late, &step_end);
-
- return ret;
-}
-
-static GstFlowReturn
-gst_base_sink_wait_event (GstBaseSink * basesink, GstEvent * event)
-{
- GstFlowReturn ret;
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- if (G_LIKELY (bclass->wait_event))
- ret = bclass->wait_event (basesink, event);
- else
- ret = GST_FLOW_NOT_SUPPORTED;
-
- return ret;
-}
-
-static gboolean
-gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
-{
- gboolean result = TRUE;
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- {
- GST_DEBUG_OBJECT (basesink, "flush-start %p", event);
- gst_base_sink_flush_start (basesink, basesink->sinkpad);
- break;
- }
- case GST_EVENT_FLUSH_STOP:
- {
- gboolean reset_time;
-
- gst_event_parse_flush_stop (event, &reset_time);
- GST_DEBUG_OBJECT (basesink, "flush-stop %p, reset_time: %d", event,
- reset_time);
- gst_base_sink_flush_stop (basesink, basesink->sinkpad, reset_time);
- break;
- }
- case GST_EVENT_EOS:
- {
- GstMessage *message;
- guint32 seqnum;
-
- /* we set the received EOS flag here so that we can use it when testing if
- * we are prerolled and to refuse more buffers. */
- basesink->priv->received_eos = TRUE;
-
- /* wait for EOS */
- if (G_UNLIKELY (gst_base_sink_wait_event (basesink,
- event) != GST_FLOW_OK)) {
- result = FALSE;
- goto done;
- }
-
- /* the EOS event is completely handled so we mark
- * ourselves as being in the EOS state. eos is also
- * protected by the object lock so we can read it when
- * answering the POSITION query. */
- GST_OBJECT_LOCK (basesink);
- basesink->eos = TRUE;
- GST_OBJECT_UNLOCK (basesink);
-
- /* ok, now we can post the message */
- GST_DEBUG_OBJECT (basesink, "Now posting EOS");
-
- seqnum = basesink->priv->seqnum = gst_event_get_seqnum (event);
- GST_DEBUG_OBJECT (basesink, "Got seqnum #%" G_GUINT32_FORMAT, seqnum);
-
- message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
- gst_message_set_seqnum (message, seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
- break;
- }
- case GST_EVENT_STREAM_START:
- {
- GstMessage *message;
- guint32 seqnum;
- guint group_id;
-
- seqnum = gst_event_get_seqnum (event);
- GST_DEBUG_OBJECT (basesink, "Now posting STREAM_START (seqnum:%d)",
- seqnum);
- message = gst_message_new_stream_start (GST_OBJECT_CAST (basesink));
- if (gst_event_parse_group_id (event, &group_id)) {
- gst_message_set_group_id (message, group_id);
- } else {
- GST_FIXME_OBJECT (basesink, "stream-start event without group-id. "
- "Consider implementing group-id handling in the upstream "
- "elements");
- }
- gst_message_set_seqnum (message, seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
- break;
- }
- case GST_EVENT_CAPS:
- {
- GstCaps *caps, *current_caps;
-
- GST_DEBUG_OBJECT (basesink, "caps %p", event);
-
- gst_event_parse_caps (event, &caps);
- current_caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (basesink));
-
- if (current_caps && gst_caps_is_equal (current_caps, caps)) {
- GST_DEBUG_OBJECT (basesink,
- "New caps equal to old ones: %" GST_PTR_FORMAT, caps);
- } else {
- if (bclass->set_caps)
- result = bclass->set_caps (basesink, caps);
-
- if (result) {
- GST_OBJECT_LOCK (basesink);
- gst_caps_replace (&basesink->priv->caps, caps);
- GST_OBJECT_UNLOCK (basesink);
- }
- }
- if (current_caps)
- gst_caps_unref (current_caps);
- break;
- }
- case GST_EVENT_SEGMENT:{
- guint32 seqnum = gst_event_get_seqnum (event);
- GstSegment new_segment;
-
- /* configure the segment */
- /* The segment is protected with both the STREAM_LOCK and the OBJECT_LOCK.
- * We protect with the OBJECT_LOCK so that we can use the values to
- * safely answer a POSITION query. */
- GST_OBJECT_LOCK (basesink);
- /* the new segment event is needed to bring the buffer timestamps to the
- * stream time and to drop samples outside of the playback segment. */
-
- gst_event_copy_segment (event, &new_segment);
-
- GST_DEBUG_OBJECT (basesink,
- "received upstream segment %u %" GST_SEGMENT_FORMAT, seqnum,
- &new_segment);
-
- /* Make sure that the position stays between start and stop */
- new_segment.position =
- CLAMP (new_segment.position, new_segment.start, new_segment.stop);
-
- if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
- GstClockTime upstream_duration;
- GstClockTime actual_duration;
- GstClockTime new_segment_running_time;
- GstClockTimeDiff difference;
- gboolean negative_duration;
-
- /* Calculate how much running time upstream believes has passed since
- * the last switch/segment */
- new_segment_running_time =
- gst_segment_to_running_time (&new_segment, GST_FORMAT_TIME,
- new_segment.position);
-
- GST_DEBUG_OBJECT (basesink,
- "Current upstream running time %" GST_TIME_FORMAT
- ", last upstream running time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (new_segment_running_time),
- GST_TIME_ARGS (basesink->priv->last_anchor_running_time -
- basesink->priv->instant_rate_offset));
-
- /* Due to rounding errors and other inaccuracies, it can happen
- * that our calculated internal running time is before the upstream
- * running time. We need to compensate for that */
- if (new_segment_running_time <
- basesink->priv->last_anchor_running_time -
- basesink->priv->instant_rate_offset) {
- upstream_duration =
- basesink->priv->last_anchor_running_time -
- basesink->priv->instant_rate_offset - new_segment_running_time;
- negative_duration = TRUE;
- } else {
- upstream_duration =
- new_segment_running_time -
- basesink->priv->last_anchor_running_time +
- basesink->priv->instant_rate_offset;
- negative_duration = FALSE;
- }
-
- /* Calculate the actual running-time duration of the previous segment */
- actual_duration =
- (upstream_duration * basesink->priv->instant_rate_multiplier);
-
- if (negative_duration)
- difference = upstream_duration - actual_duration;
- else
- difference = actual_duration - upstream_duration;
-
- GST_DEBUG_OBJECT (basesink,
- "Current internal running time %" GST_TIME_FORMAT
- ", last internal running time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (new_segment_running_time +
- basesink->priv->instant_rate_offset + difference),
- GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
-
- /* Add the difference to the previously accumulated correction. */
- basesink->priv->instant_rate_offset += difference;
-
- GST_DEBUG_OBJECT (basesink,
- "Updating instant rate correction offset. Actual duration %"
- GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
- ", negative %d, difference %" GST_STIME_FORMAT ", new offset %"
- GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
- GST_TIME_ARGS (upstream_duration),
- negative_duration,
- GST_STIME_ARGS (difference),
- GST_STIME_ARGS (basesink->priv->instant_rate_offset));
-
- if (basesink->priv->instant_rate_offset < 0 &&
- new_segment_running_time < -basesink->priv->instant_rate_offset) {
- GST_WARNING_OBJECT (basesink,
- "Upstream current running time %" GST_TIME_FORMAT
- " is smaller than calculated offset %" GST_STIME_FORMAT,
- GST_TIME_ARGS (new_segment_running_time),
- GST_STIME_ARGS (basesink->priv->instant_rate_offset));
-
- basesink->priv->last_anchor_running_time = 0;
- basesink->priv->instant_rate_offset = 0;
- } else {
- basesink->priv->last_anchor_running_time =
- new_segment_running_time + basesink->priv->instant_rate_offset;
- }
-
- /* Update the segments from the event and with the newly calculated
- * correction offset */
- basesink->priv->upstream_segment = new_segment;
- basesink->segment = new_segment;
-
- basesink->segment.rate *= basesink->priv->instant_rate_multiplier;
-
- gst_segment_offset_running_time (&basesink->segment, GST_FORMAT_TIME,
- basesink->priv->instant_rate_offset);
-
- GST_DEBUG_OBJECT (basesink,
- "Adjusted segment is now %" GST_SEGMENT_FORMAT, &basesink->segment);
- } else {
- /* otherwise both segments are simply the same, no correction needed */
- basesink->priv->upstream_segment = new_segment;
- basesink->segment = new_segment;
- basesink->priv->last_anchor_running_time =
- gst_segment_to_running_time (&new_segment, new_segment.format,
- new_segment.position);
- basesink->priv->instant_rate_offset = 0; /* Should already be 0, but to be sure */
- }
-
- GST_DEBUG_OBJECT (basesink, "configured segment %" GST_SEGMENT_FORMAT,
- &basesink->segment);
- basesink->priv->segment_seqnum = seqnum;
- basesink->have_newsegment = TRUE;
- gst_base_sink_reset_qos (basesink);
- GST_OBJECT_UNLOCK (basesink);
- break;
- }
- case GST_EVENT_GAP:
- {
- if (G_UNLIKELY (gst_base_sink_wait_event (basesink,
- event) != GST_FLOW_OK))
- result = FALSE;
- break;
- }
- case GST_EVENT_TAG:
- {
- GstTagList *taglist;
-
- gst_event_parse_tag (event, &taglist);
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_tag (GST_OBJECT_CAST (basesink),
- gst_tag_list_copy (taglist)));
- break;
- }
- case GST_EVENT_TOC:
- {
- GstToc *toc;
- gboolean updated;
-
- gst_event_parse_toc (event, &toc, &updated);
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_toc (GST_OBJECT_CAST (basesink), toc, updated));
-
- gst_toc_unref (toc);
- break;
- }
- case GST_EVENT_SINK_MESSAGE:
- {
- GstMessage *msg = NULL;
-
- gst_event_parse_sink_message (event, &msg);
- if (msg)
- gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
- break;
- }
- case GST_EVENT_INSTANT_RATE_CHANGE:
- {
- GstMessage *msg;
- gdouble rate_multiplier;
- guint32 seqnum = gst_event_get_seqnum (event);
-
- GST_OBJECT_LOCK (basesink);
- if (G_UNLIKELY (basesink->priv->last_instant_rate_seqnum == seqnum)) {
- /* Ignore repeated event */
- GST_LOG_OBJECT (basesink,
- "Ignoring repeated instant-rate-change event");
- GST_OBJECT_UNLOCK (basesink);
- break;
- }
- if (basesink->priv->instant_rate_sync_seqnum == seqnum) {
- /* Ignore if we already received the instant-rate-sync-time event from the pipeline */
- GST_LOG_OBJECT (basesink,
- "Ignoring instant-rate-change event for which we already received instant-rate-sync-time");
- GST_OBJECT_UNLOCK (basesink);
- break;
- }
-
- basesink->priv->last_instant_rate_seqnum = seqnum;
- GST_OBJECT_UNLOCK (basesink);
-
- gst_event_parse_instant_rate_change (event, &rate_multiplier, NULL);
-
- msg =
- gst_message_new_instant_rate_request (GST_OBJECT_CAST (basesink),
- rate_multiplier);
- gst_message_set_seqnum (msg, seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
-
- break;
- }
- default:
- break;
- }
-done:
- gst_event_unref (event);
-
- return result;
-}
-
-static gboolean
-gst_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstBaseSink *basesink;
- gboolean result = TRUE;
- GstBaseSinkClass *bclass;
-
- basesink = GST_BASE_SINK_CAST (parent);
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- GST_DEBUG_OBJECT (basesink, "received event %p %" GST_PTR_FORMAT, event,
- event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- /* special case for this serialized event because we don't want to grab
- * the PREROLL lock or check if we were flushing */
- if (bclass->event)
- result = bclass->event (basesink, event);
- break;
- default:
- if (GST_EVENT_IS_SERIALIZED (event)) {
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- if (G_UNLIKELY (basesink->flushing))
- goto flushing;
-
- if (G_UNLIKELY (basesink->priv->received_eos))
- goto after_eos;
-
- if (bclass->event)
- result = bclass->event (basesink, event);
-
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- } else {
- if (bclass->event)
- result = bclass->event (basesink, event);
- }
- break;
- }
-done:
- return result;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (basesink, "we are flushing");
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- gst_event_unref (event);
- result = FALSE;
- goto done;
- }
-
-after_eos:
- {
- GST_DEBUG_OBJECT (basesink, "Event received after EOS, dropping");
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- gst_event_unref (event);
- result = FALSE;
- goto done;
- }
-}
-
-/* default implementation to calculate the start and end
- * timestamps on a buffer, subclasses can override
- */
-static void
-gst_base_sink_default_get_times (GstBaseSink * basesink, GstBuffer * buffer,
- GstClockTime * start, GstClockTime * end)
-{
- GstClockTime timestamp, duration;
-
- /* first sync on DTS, else use PTS */
- timestamp = GST_BUFFER_DTS (buffer);
- if (!GST_CLOCK_TIME_IS_VALID (timestamp))
- timestamp = GST_BUFFER_PTS (buffer);
-
- if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
- /* get duration to calculate end time */
- duration = GST_BUFFER_DURATION (buffer);
- if (GST_CLOCK_TIME_IS_VALID (duration)) {
- *end = timestamp + duration;
- }
- *start = timestamp;
- }
-}
-
-/* must be called with PREROLL_LOCK */
-static gboolean
-gst_base_sink_needs_preroll (GstBaseSink * basesink)
-{
- gboolean is_prerolled, res;
-
- /* we have 2 cases where the PREROLL_LOCK is released:
- * 1) we are blocking in the PREROLL_LOCK and thus are prerolled.
- * 2) we are syncing on the clock
- */
- is_prerolled = basesink->have_preroll || basesink->priv->received_eos;
- res = !is_prerolled;
-
- GST_DEBUG_OBJECT (basesink, "have_preroll: %d, EOS: %d => needs preroll: %d",
- basesink->have_preroll, basesink->priv->received_eos, res);
-
- return res;
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Takes a buffer and compare the timestamps with the last segment.
- * If the buffer falls outside of the segment boundaries, drop it.
- * Else send the buffer for preroll and rendering.
- *
- * This function takes ownership of the buffer.
- */
-static GstFlowReturn
-gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
- gpointer obj, gboolean is_list)
-{
- GstBaseSinkClass *bclass;
- GstBaseSinkPrivate *priv = basesink->priv;
- GstFlowReturn ret = GST_FLOW_OK;
- GstClockTime start = GST_CLOCK_TIME_NONE, end = GST_CLOCK_TIME_NONE;
- GstSegment *segment;
- GstBuffer *sync_buf;
- gboolean late, step_end, prepared = FALSE;
-
- if (G_UNLIKELY (basesink->flushing))
- goto flushing;
-
- if (G_UNLIKELY (priv->received_eos))
- goto was_eos;
-
- if (is_list) {
- GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (obj);
-
- if (gst_buffer_list_length (buffer_list) == 0)
- goto empty_list;
-
- sync_buf = gst_buffer_list_get (buffer_list, 0);
- g_assert (NULL != sync_buf);
- } else {
- sync_buf = GST_BUFFER_CAST (obj);
- }
-
- /* for code clarity */
- segment = &basesink->segment;
-
- if (G_UNLIKELY (!basesink->have_newsegment)) {
- gboolean sync;
-
- sync = gst_base_sink_get_sync (basesink);
- if (sync) {
- GST_ELEMENT_WARNING (basesink, STREAM, FAILED,
- (_("Internal data flow problem.")),
- ("Received buffer without a new-segment. Assuming timestamps start from 0."));
- }
-
- /* this means this sink will assume timestamps start from 0 */
- GST_OBJECT_LOCK (basesink);
- segment->start = 0;
- segment->stop = -1;
- basesink->segment.start = 0;
- basesink->segment.stop = -1;
- basesink->have_newsegment = TRUE;
- GST_OBJECT_UNLOCK (basesink);
- }
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- /* check if the buffer needs to be dropped, we first ask the subclass for the
- * start and end */
- if (bclass->get_times)
- bclass->get_times (basesink, sync_buf, &start, &end);
-
- if (!GST_CLOCK_TIME_IS_VALID (start)) {
- /* if the subclass does not want sync, we use our own values so that we at
- * least clip the buffer to the segment */
- gst_base_sink_default_get_times (basesink, sync_buf, &start, &end);
- }
-
- GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
- ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
-
- /* a dropped buffer does not participate in anything. Buffer can only be
- * dropped if their PTS falls completely outside the segment, while we sync
- * preferably on DTS */
- if (GST_CLOCK_TIME_IS_VALID (start) && (segment->format == GST_FORMAT_TIME)) {
- GstClockTime pts = GST_BUFFER_PTS (sync_buf);
- GstClockTime pts_end = GST_CLOCK_TIME_NONE;
-
- if (!GST_CLOCK_TIME_IS_VALID (pts))
- pts = start;
-
- if (GST_CLOCK_TIME_IS_VALID (end))
- pts_end = pts + (end - start);
-
- if (G_UNLIKELY (!gst_segment_clip (segment,
- GST_FORMAT_TIME, pts, pts_end, NULL, NULL)
- && priv->drop_out_of_segment))
- goto out_of_segment;
- }
-
- if (bclass->prepare || bclass->prepare_list) {
- gboolean do_sync = TRUE, stepped = FALSE, syncable = TRUE;
- GstClockTime sstart, sstop, rstart, rstop, rnext;
- GstStepInfo *current;
-
- late = FALSE;
- step_end = FALSE;
-
- current = &priv->current_step;
- syncable =
- gst_base_sink_get_sync_times (basesink, obj, &sstart, &sstop, &rstart,
- &rstop, &rnext, &do_sync, &stepped, current, &step_end);
-
- if (G_UNLIKELY (stepped))
- goto dropped;
-
- if (syncable && do_sync && gst_base_sink_get_sync (basesink)) {
- GstClock *clock;
-
- GST_OBJECT_LOCK (basesink);
- clock = GST_ELEMENT_CLOCK (basesink);
- if (clock && GST_STATE (basesink) == GST_STATE_PLAYING) {
- GstClockTime base_time;
- GstClockTime stime;
- GstClockTime now;
-
- base_time = GST_ELEMENT_CAST (basesink)->base_time;
- stime = base_time + gst_base_sink_adjust_time (basesink, rstart);
- now = gst_clock_get_time (clock);
- GST_OBJECT_UNLOCK (basesink);
-
- late =
- gst_base_sink_is_too_late (basesink, obj, rstart, rstop,
- GST_CLOCK_EARLY, GST_CLOCK_DIFF (stime, now), FALSE);
- } else {
- GST_OBJECT_UNLOCK (basesink);
- }
- }
-
- /* We are about to prepare the first frame, make sure we have prerolled
- * already. This prevent nesting prepare/render calls. */
- ret = gst_base_sink_do_preroll (basesink, obj);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto preroll_failed;
-
- if (G_UNLIKELY (late))
- goto dropped;
-
- if (!is_list) {
- if (bclass->prepare) {
- ret = bclass->prepare (basesink, GST_BUFFER_CAST (obj));
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto prepare_failed;
- }
- } else {
- if (bclass->prepare_list) {
- ret = bclass->prepare_list (basesink, GST_BUFFER_LIST_CAST (obj));
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto prepare_failed;
- }
- }
-
- prepared = TRUE;
- }
-
-again:
- late = FALSE;
- step_end = FALSE;
-
- /* synchronize this object, non syncable objects return OK
- * immediately. */
- ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (sync_buf),
- &late, &step_end);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto sync_failed;
-
- /* Don't skip if prepare() was called on time */
- late = late && !prepared;
-
- /* drop late buffers unconditionally, let's hope it's unlikely */
- if (G_UNLIKELY (late))
- goto dropped;
-
- if (priv->max_bitrate) {
- gsize size;
-
- if (is_list)
- size = gst_buffer_list_calculate_size (GST_BUFFER_LIST_CAST (obj));
- else
- size = gst_buffer_get_size (GST_BUFFER_CAST (obj));
-
- priv->rc_accumulated += size;
- priv->rc_next = priv->rc_time + gst_util_uint64_scale (priv->rc_accumulated,
- 8 * GST_SECOND, priv->max_bitrate);
- }
-
- GST_DEBUG_OBJECT (basesink, "rendering object %p", obj);
-
- if (!is_list) {
- /* For buffer lists do not set last buffer for now. */
- gst_base_sink_set_last_buffer (basesink, GST_BUFFER_CAST (obj));
- gst_base_sink_set_last_buffer_list (basesink, NULL);
-
- if (bclass->render)
- ret = bclass->render (basesink, GST_BUFFER_CAST (obj));
- } else {
- GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (obj);
-
- if (bclass->render_list)
- ret = bclass->render_list (basesink, buffer_list);
-
- /* Set the first buffer and buffer list to be included in last sample */
- gst_base_sink_set_last_buffer (basesink, sync_buf);
- gst_base_sink_set_last_buffer_list (basesink, buffer_list);
- }
-
- if (ret == GST_FLOW_STEP)
- goto again;
-
- if (G_UNLIKELY (basesink->flushing))
- goto flushing;
-
- priv->rendered++;
-
-done:
- if (step_end) {
- /* the step ended, check if we need to activate a new step */
- GST_DEBUG_OBJECT (basesink, "step ended");
- stop_stepping (basesink, &basesink->segment, &priv->current_step,
- priv->current_rstart, priv->current_rstop, basesink->eos);
- goto again;
- }
-
- gst_base_sink_perform_qos (basesink, late);
-
- GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
-
- return ret;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (basesink, "sink is flushing");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return GST_FLOW_FLUSHING;
- }
-was_eos:
- {
- GST_DEBUG_OBJECT (basesink, "we are EOS, dropping object, return EOS");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return GST_FLOW_EOS;
- }
-empty_list:
- {
- GST_DEBUG_OBJECT (basesink, "buffer list with no buffers");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return GST_FLOW_OK;
- }
-out_of_segment:
- {
- GST_DEBUG_OBJECT (basesink, "dropping buffer, out of clipping segment");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return GST_FLOW_OK;
- }
-prepare_failed:
- {
- GST_DEBUG_OBJECT (basesink, "prepare buffer failed %s",
- gst_flow_get_name (ret));
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return ret;
- }
-sync_failed:
- {
- GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret));
- goto done;
- }
-dropped:
- {
- priv->dropped++;
- GST_DEBUG_OBJECT (basesink, "buffer late, dropping");
-
- if (g_atomic_int_get (&priv->qos_enabled)) {
- GstMessage *qos_msg;
- GstClockTime timestamp, duration;
-
- timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (sync_buf));
- duration = GST_BUFFER_DURATION (GST_BUFFER_CAST (sync_buf));
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
- "qos: dropped buffer rt %" GST_TIME_FORMAT ", st %" GST_TIME_FORMAT
- ", ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
- GST_TIME_ARGS (priv->current_rstart),
- GST_TIME_ARGS (priv->current_sstart), GST_TIME_ARGS (timestamp),
- GST_TIME_ARGS (duration));
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
- "qos: rendered %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT,
- priv->rendered, priv->dropped);
-
- qos_msg =
- gst_message_new_qos (GST_OBJECT_CAST (basesink), basesink->sync,
- priv->current_rstart, priv->current_sstart, timestamp, duration);
- gst_message_set_qos_values (qos_msg, priv->current_jitter, priv->avg_rate,
- 1000000);
- gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, priv->rendered,
- priv->dropped);
- gst_element_post_message (GST_ELEMENT_CAST (basesink), qos_msg);
- }
- goto done;
- }
-preroll_failed:
- {
- GST_DEBUG_OBJECT (basesink, "preroll failed: %s", gst_flow_get_name (ret));
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- return ret;
- }
-}
-
-/* with STREAM_LOCK
- */
-static GstFlowReturn
-gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj,
- gboolean is_list)
-{
- GstFlowReturn result;
-
- if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH))
- goto wrong_mode;
-
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- result = gst_base_sink_chain_unlocked (basesink, pad, obj, is_list);
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
-
-done:
- return result;
-
- /* ERRORS */
-wrong_mode:
- {
- GST_OBJECT_LOCK (pad);
- GST_WARNING_OBJECT (basesink,
- "Push on pad %s:%s, but it was not activated in push mode",
- GST_DEBUG_PAD_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
- /* we don't post an error message this will signal to the peer
- * pushing that EOS is reached. */
- result = GST_FLOW_EOS;
- goto done;
- }
-}
-
-static GstFlowReturn
-gst_base_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
-{
- GstBaseSink *basesink;
-
- basesink = GST_BASE_SINK (parent);
-
- return gst_base_sink_chain_main (basesink, pad, buf, FALSE);
-}
-
-static GstFlowReturn
-gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
- GstBufferList * list)
-{
- GstBaseSink *basesink;
- GstBaseSinkClass *bclass;
- GstFlowReturn result;
-
- basesink = GST_BASE_SINK (parent);
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- if (G_LIKELY (bclass->render_list)) {
- result = gst_base_sink_chain_main (basesink, pad, list, TRUE);
- } else {
- guint i, len;
- GstBuffer *buffer;
-
- GST_LOG_OBJECT (pad, "chaining each buffer in list");
-
- len = gst_buffer_list_length (list);
-
- result = GST_FLOW_OK;
- for (i = 0; i < len; i++) {
- buffer = gst_buffer_list_get (list, i);
- result = gst_base_sink_chain_main (basesink, pad,
- gst_buffer_ref (buffer), FALSE);
- if (result != GST_FLOW_OK)
- break;
- }
- gst_buffer_list_unref (list);
- }
- return result;
-}
-
-
-static gboolean
-gst_base_sink_default_do_seek (GstBaseSink * sink, GstSegment * segment)
-{
- gboolean res = TRUE;
-
- /* update our offset if the start/stop position was updated */
- if (segment->format == GST_FORMAT_BYTES) {
- segment->time = segment->start;
- } else if (segment->start == 0) {
- /* seek to start, we can implement a default for this. */
- segment->time = 0;
- } else {
- res = FALSE;
- GST_INFO_OBJECT (sink, "Can't do a default seek");
- }
-
- return res;
-}
-
-#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))
-
-static gboolean
-gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
- GstEvent * event, GstSegment * segment)
-{
- /* By default, we try one of 2 things:
- * - For absolute seek positions, convert the requested position to our
- * configured processing format and place it in the output segment \
- * - For relative seek positions, convert our current (input) values to the
- * seek format, adjust by the relative seek offset and then convert back to
- * the processing format
- */
- GstSeekType start_type, stop_type;
- gint64 start, stop;
- GstSeekFlags flags;
- GstFormat seek_format;
- gdouble rate;
- gboolean update;
- gboolean res = TRUE;
-
- gst_event_parse_seek (event, &rate, &seek_format, &flags,
- &start_type, &start, &stop_type, &stop);
-
- if (seek_format == segment->format) {
- gst_segment_do_seek (segment, rate, seek_format, flags,
- start_type, start, stop_type, stop, &update);
- return TRUE;
- }
-
- if (start_type != GST_SEEK_TYPE_NONE) {
- /* FIXME: Handle seek_end by converting the input segment vals */
- res =
- gst_pad_query_convert (sink->sinkpad, seek_format, start,
- segment->format, &start);
- start_type = GST_SEEK_TYPE_SET;
- }
-
- if (res && stop_type != GST_SEEK_TYPE_NONE) {
- /* FIXME: Handle seek_end by converting the input segment vals */
- res =
- gst_pad_query_convert (sink->sinkpad, seek_format, stop,
- segment->format, &stop);
- stop_type = GST_SEEK_TYPE_SET;
- }
-
- /* And finally, configure our output segment in the desired format */
- gst_segment_do_seek (segment, rate, segment->format, flags, start_type, start,
- stop_type, stop, &update);
-
- if (!res)
- goto no_format;
-
- return res;
-
-no_format:
- {
- GST_DEBUG_OBJECT (sink, "undefined format given, seek aborted.");
- return FALSE;
- }
-}
-
-/* perform a seek, only executed in pull mode */
-static gboolean
-gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
-{
- gboolean flush;
- gdouble rate;
- GstFormat seek_format, dest_format;
- GstSeekFlags flags;
- GstSeekType start_type, stop_type;
- gboolean seekseg_configured = FALSE;
- gint64 start, stop;
- gboolean update, res = TRUE;
- GstSegment seeksegment;
-
- dest_format = sink->segment.format;
-
- if (event) {
- GST_DEBUG_OBJECT (sink, "performing seek with event %p", event);
- gst_event_parse_seek (event, &rate, &seek_format, &flags,
- &start_type, &start, &stop_type, &stop);
-
- flush = flags & GST_SEEK_FLAG_FLUSH;
- } else {
- GST_DEBUG_OBJECT (sink, "performing seek without event");
- flush = FALSE;
- }
-
- if (flush) {
- GST_DEBUG_OBJECT (sink, "flushing upstream");
- gst_pad_push_event (pad, gst_event_new_flush_start ());
- gst_base_sink_flush_start (sink, pad);
- } else {
- GST_DEBUG_OBJECT (sink, "pausing pulling thread");
- }
-
- GST_PAD_STREAM_LOCK (pad);
-
- /* If we configured the seeksegment above, don't overwrite it now. Otherwise
- * copy the current segment info into the temp segment that we can actually
- * attempt the seek with. We only update the real segment if the seek succeeds. */
- if (!seekseg_configured) {
- memcpy (&seeksegment, &sink->segment, sizeof (GstSegment));
-
- /* now configure the final seek segment */
- if (event) {
- if (sink->segment.format != seek_format) {
- /* OK, here's where we give the subclass a chance to convert the relative
- * seek into an absolute one in the processing format. We set up any
- * absolute seek above, before taking the stream lock. */
- if (!gst_base_sink_default_prepare_seek_segment (sink, event,
- &seeksegment)) {
- GST_DEBUG_OBJECT (sink,
- "Preparing the seek failed after flushing. " "Aborting seek");
- res = FALSE;
- }
- } else {
- /* The seek format matches our processing format, no need to ask the
- * the subclass to configure the segment. */
- gst_segment_do_seek (&seeksegment, rate, seek_format, flags,
- start_type, start, stop_type, stop, &update);
- }
- }
- /* Else, no seek event passed, so we're just (re)starting the
- current segment. */
- }
-
- if (res) {
- GST_DEBUG_OBJECT (sink, "segment configured from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
- seeksegment.start, seeksegment.stop, seeksegment.position);
-
- /* do the seek, segment.position contains the new position. */
- res = gst_base_sink_default_do_seek (sink, &seeksegment);
- }
-
- if (flush) {
- GST_DEBUG_OBJECT (sink, "stop flushing upstream");
- gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
- gst_base_sink_flush_stop (sink, pad, TRUE);
- } else if (res && sink->running) {
- /* we are running the current segment and doing a non-flushing seek,
- * close the segment first based on the position. */
- GST_DEBUG_OBJECT (sink, "closing running segment %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, sink->segment.start, sink->segment.position);
- }
-
- /* The subclass must have converted the segment to the processing format
- * by now */
- if (res && seeksegment.format != dest_format) {
- GST_DEBUG_OBJECT (sink, "Subclass failed to prepare a seek segment "
- "in the correct format. Aborting seek.");
- res = FALSE;
- }
-
- GST_INFO_OBJECT (sink, "seeking done %d: %" GST_SEGMENT_FORMAT, res,
- &seeksegment);
-
- /* if successful seek, we update our real segment and push
- * out the new segment. */
- if (res) {
- gst_segment_copy_into (&seeksegment, &sink->segment);
-
- if (sink->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
- gst_element_post_message (GST_ELEMENT (sink),
- gst_message_new_segment_start (GST_OBJECT (sink),
- sink->segment.format, sink->segment.position));
- }
- }
-
- sink->priv->discont = TRUE;
- sink->running = TRUE;
-
- GST_PAD_STREAM_UNLOCK (pad);
-
- return res;
-}
-
-static void
-set_step_info (GstBaseSink * sink, GstStepInfo * current, GstStepInfo * pending,
- guint seqnum, GstFormat format, guint64 amount, gdouble rate,
- gboolean flush, gboolean intermediate)
-{
- GST_OBJECT_LOCK (sink);
- pending->seqnum = seqnum;
- pending->format = format;
- pending->amount = amount;
- pending->position = 0;
- pending->rate = rate;
- pending->flush = flush;
- pending->intermediate = intermediate;
- pending->valid = TRUE;
- /* flush invalidates the current stepping segment */
- if (flush)
- current->valid = FALSE;
- GST_OBJECT_UNLOCK (sink);
-}
-
-static gboolean
-gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
-{
- GstBaseSinkPrivate *priv;
- GstBaseSinkClass *bclass;
- gboolean flush, intermediate;
- gdouble rate;
- GstFormat format;
- guint64 amount;
- guint seqnum;
- GstStepInfo *pending, *current;
- GstMessage *message;
-
- bclass = GST_BASE_SINK_GET_CLASS (sink);
- priv = sink->priv;
-
- GST_DEBUG_OBJECT (sink, "performing step with event %p", event);
-
- gst_event_parse_step (event, &format, &amount, &rate, &flush, &intermediate);
- seqnum = gst_event_get_seqnum (event);
-
- pending = &priv->pending_step;
- current = &priv->current_step;
-
- /* post message first */
- message = gst_message_new_step_start (GST_OBJECT (sink), FALSE, format,
- amount, rate, flush, intermediate);
- gst_message_set_seqnum (message, seqnum);
- gst_element_post_message (GST_ELEMENT (sink), message);
-
- if (flush) {
- /* we need to call ::unlock before locking PREROLL_LOCK
- * since we lock it before going into ::render */
- if (bclass->unlock)
- bclass->unlock (sink);
-
- GST_BASE_SINK_PREROLL_LOCK (sink);
- /* now that we have the PREROLL lock, clear our unlock request */
- if (bclass->unlock_stop)
- bclass->unlock_stop (sink);
-
- /* update the stepinfo and make it valid */
- set_step_info (sink, current, pending, seqnum, format, amount, rate, flush,
- intermediate);
-
- if (sink->priv->async_enabled) {
- /* and we need to commit our state again on the next
- * prerolled buffer */
- sink->playing_async = TRUE;
- priv->pending_step.need_preroll = TRUE;
- sink->need_preroll = FALSE;
- gst_base_sink_update_start_time (sink);
- gst_element_lost_state (GST_ELEMENT_CAST (sink));
- } else {
- sink->priv->have_latency = TRUE;
- sink->need_preroll = FALSE;
- }
- priv->current_sstart = GST_CLOCK_TIME_NONE;
- priv->current_sstop = GST_CLOCK_TIME_NONE;
- priv->eos_rtime = GST_CLOCK_TIME_NONE;
- priv->call_preroll = TRUE;
- gst_base_sink_set_last_buffer (sink, NULL);
- gst_base_sink_set_last_buffer_list (sink, NULL);
- gst_base_sink_reset_qos (sink);
-
- if (sink->clock_id) {
- gst_clock_id_unschedule (sink->clock_id);
- }
-
- if (sink->have_preroll) {
- GST_DEBUG_OBJECT (sink, "signal waiter");
- priv->step_unlock = TRUE;
- GST_BASE_SINK_PREROLL_SIGNAL (sink);
- }
- GST_BASE_SINK_PREROLL_UNLOCK (sink);
- } else {
- /* update the stepinfo and make it valid */
- set_step_info (sink, current, pending, seqnum, format, amount, rate, flush,
- intermediate);
- }
-
- return TRUE;
-}
-
-static gboolean
-gst_base_sink_perform_instant_rate_change (GstBaseSink * sink, GstPad * pad,
- GstEvent * event)
-{
- GstBaseSinkPrivate *priv;
- guint32 seqnum;
- gdouble rate;
- GstClockTime running_time, upstream_running_time;
-
- GstClockTime switch_time;
- gint res;
-
- priv = sink->priv;
-
- GST_DEBUG_OBJECT (sink, "performing instant-rate-change with event %p",
- event);
-
- seqnum = gst_event_get_seqnum (event);
- gst_event_parse_instant_rate_sync_time (event, &rate, &running_time,
- &upstream_running_time);
-
- GST_DEBUG_OBJECT (sink, "instant-rate-change %u %lf at %" GST_TIME_FORMAT
- ", upstream %" GST_TIME_FORMAT,
- seqnum, rate, GST_TIME_ARGS (running_time),
- GST_TIME_ARGS (upstream_running_time));
-
- /* Take the preroll lock so we can change the segment. We do not call unlock
- * like for stepping as that would cause the PLAYING state to be lost and
- * would get us into prerolling again first
- *
- * FIXME: The below potentially blocks until the chain function returns, but
- * the lock is not taken during all waiting operations inside the chain
- * function (clock, preroll) so this should be fine in most cases. Only
- * problem is if the render() or prepare() functions are waiting themselves!
- *
- * FIXME: If the subclass is calling gst_base_sink_wait() it will be woken
- * up but there is no way for it to update the timestamps, or to report back
- * to the base class that it should recalculate the values. The current
- * change would not be instantaneous in that case but would wait until the
- * next buffer.
- */
- GST_BASE_SINK_PREROLL_LOCK (sink);
-
- /* We can safely change the segment and everything here as we hold the
- * PREROLL_LOCK and it is taken for the whole chain function */
- sink->priv->instant_rate_sync_seqnum = seqnum;
- sink->priv->instant_rate_multiplier = rate;
- sink->priv->instant_rate_offset = running_time - upstream_running_time;
- sink->priv->last_anchor_running_time = running_time;
-
- GST_DEBUG_OBJECT (sink, "Current internal running time %" GST_TIME_FORMAT
- ", last internal running time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (running_time),
- GST_TIME_ARGS (sink->priv->last_anchor_running_time));
-
- /* Calculate the current position in the segment and do a seek with the
- * new rate. This updates rate, base and offset accordingly */
- res =
- gst_segment_position_from_running_time_full (&sink->segment,
- GST_FORMAT_TIME, running_time, &switch_time);
-
- GST_DEBUG_OBJECT (sink, "Before adjustment seg is %" GST_SEGMENT_FORMAT
- " new running_time %" GST_TIME_FORMAT
- " position %" GST_STIME_FORMAT " res %d", &sink->segment,
- GST_TIME_ARGS (running_time),
- GST_STIME_ARGS ((GstClockTimeDiff) switch_time), res);
-
- if (res < 0) {
- GST_WARNING_OBJECT (sink,
- "Negative position calculated. Can't instant-rate change to there");
- GST_BASE_SINK_PREROLL_UNLOCK (sink);
- return TRUE;
- }
-
- sink->segment.position = switch_time;
-
- /* Calculate new output rate based on upstream value */
- rate *= sink->priv->upstream_segment.rate;
-
- gst_segment_do_seek (&sink->segment, rate, GST_FORMAT_TIME,
- sink->segment.flags & (~GST_SEEK_FLAG_FLUSH) &
- GST_SEEK_FLAG_INSTANT_RATE_CHANGE, GST_SEEK_TYPE_NONE, -1,
- GST_SEEK_TYPE_NONE, -1, NULL);
-
- GST_DEBUG_OBJECT (sink, "Adjusted segment is now %" GST_SEGMENT_FORMAT,
- &sink->segment);
-
- priv->current_sstart = GST_CLOCK_TIME_NONE;
- priv->current_sstop = GST_CLOCK_TIME_NONE;
- priv->eos_rtime = GST_CLOCK_TIME_NONE;
- gst_base_sink_reset_qos (sink);
-
- if (sink->clock_id) {
- gst_clock_id_unschedule (sink->clock_id);
- }
-
- if (sink->have_preroll) {
- GST_DEBUG_OBJECT (sink, "signal waiter");
- /* TODO: Rename this, and GST_FLOW_STEP */
- priv->step_unlock = TRUE;
- GST_BASE_SINK_PREROLL_SIGNAL (sink);
- }
-
- GST_BASE_SINK_PREROLL_UNLOCK (sink);
-
- return TRUE;
-}
-
-/* with STREAM_LOCK
- */
-static void
-gst_base_sink_loop (GstPad * pad)
-{
- GstObject *parent;
- GstBaseSink *basesink;
- GstBuffer *buf = NULL;
- GstFlowReturn result;
- guint blocksize;
- guint64 offset;
-
- parent = GST_OBJECT_PARENT (pad);
- basesink = GST_BASE_SINK (parent);
-
- g_assert (basesink->pad_mode == GST_PAD_MODE_PULL);
-
- if ((blocksize = basesink->priv->blocksize) == 0)
- blocksize = -1;
-
- offset = basesink->segment.position;
-
- GST_DEBUG_OBJECT (basesink, "pulling %" G_GUINT64_FORMAT ", %u",
- offset, blocksize);
-
- result = gst_pad_pull_range (pad, offset, blocksize, &buf);
- if (G_UNLIKELY (result != GST_FLOW_OK))
- goto paused;
-
- if (G_UNLIKELY (buf == NULL))
- goto no_buffer;
-
- offset += gst_buffer_get_size (buf);
-
- basesink->segment.position = offset;
-
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- result = gst_base_sink_chain_unlocked (basesink, pad, buf, FALSE);
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- if (G_UNLIKELY (result != GST_FLOW_OK))
- goto paused;
-
- return;
-
- /* ERRORS */
-paused:
- {
- GST_LOG_OBJECT (basesink, "pausing task, reason %s",
- gst_flow_get_name (result));
- gst_pad_pause_task (pad);
- if (result == GST_FLOW_EOS) {
- /* perform EOS logic */
- if (basesink->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_segment_done (GST_OBJECT_CAST (basesink),
- basesink->segment.format, basesink->segment.position));
- gst_base_sink_event (pad, parent,
- gst_event_new_segment_done (basesink->segment.format,
- basesink->segment.position));
- } else {
- gst_base_sink_event (pad, parent, gst_event_new_eos ());
- }
- } else if (result == GST_FLOW_NOT_LINKED || result <= GST_FLOW_EOS) {
- /* for fatal errors we post an error message, post the error
- * first so the app knows about the error first.
- * wrong-state is not a fatal error because it happens due to
- * flushing and posting an error message in that case is the
- * wrong thing to do, e.g. when basesrc is doing a flushing
- * seek. */
- GST_ELEMENT_FLOW_ERROR (basesink, result);
- gst_base_sink_event (pad, parent, gst_event_new_eos ());
- }
- return;
- }
-no_buffer:
- {
- GST_LOG_OBJECT (basesink, "no buffer, pausing");
- GST_ELEMENT_ERROR (basesink, STREAM, FAILED,
- (_("Internal data flow error.")), ("element returned NULL buffer"));
- result = GST_FLOW_ERROR;
- goto paused;
- }
-}
-
-static gboolean
-gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad,
- gboolean flushing)
-{
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- if (flushing) {
- /* unlock any subclasses, we need to do this before grabbing the
- * PREROLL_LOCK since we hold this lock before going into ::render. */
- if (bclass->unlock)
- bclass->unlock (basesink);
- }
-
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- basesink->flushing = flushing;
- if (flushing) {
- /* step 1, now that we have the PREROLL lock, clear our unlock request */
- if (bclass->unlock_stop)
- bclass->unlock_stop (basesink);
-
- /* set need_preroll before we unblock the clock. If the clock is unblocked
- * before timing out, we can reuse the buffer for preroll. */
- basesink->need_preroll = TRUE;
-
- /* step 2, unblock clock sync (if any) or any other blocking thing */
- if (basesink->clock_id) {
- gst_clock_id_unschedule (basesink->clock_id);
- }
-
- /* flush out the data thread if it's locked in finish_preroll, this will
- * also flush out the EOS state */
- GST_DEBUG_OBJECT (basesink,
- "flushing out data thread, need preroll to TRUE");
-
- /* we can't have EOS anymore now */
- basesink->eos = FALSE;
- basesink->priv->received_eos = FALSE;
- basesink->have_preroll = FALSE;
- basesink->priv->step_unlock = FALSE;
- /* can't report latency anymore until we preroll again */
- if (basesink->priv->async_enabled) {
- GST_OBJECT_LOCK (basesink);
- basesink->priv->have_latency = FALSE;
- GST_OBJECT_UNLOCK (basesink);
- }
- /* and signal any waiters now */
- GST_BASE_SINK_PREROLL_SIGNAL (basesink);
- }
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
-
- return TRUE;
-}
-
-static gboolean
-gst_base_sink_default_activate_pull (GstBaseSink * basesink, gboolean active)
-{
- gboolean result;
-
- if (active) {
- /* start task */
- result = gst_pad_start_task (basesink->sinkpad,
- (GstTaskFunction) gst_base_sink_loop, basesink->sinkpad, NULL);
- } else {
- /* step 2, make sure streaming finishes */
- result = gst_pad_stop_task (basesink->sinkpad);
- }
-
- return result;
-}
-
-static gboolean
-gst_base_sink_pad_activate (GstPad * pad, GstObject * parent)
-{
- gboolean result = FALSE;
- GstBaseSink *basesink;
- GstQuery *query;
- gboolean pull_mode;
-
- basesink = GST_BASE_SINK (parent);
-
- GST_DEBUG_OBJECT (basesink, "Trying pull mode first");
-
- gst_base_sink_set_flushing (basesink, pad, FALSE);
-
- /* we need to have the pull mode enabled */
- if (!basesink->can_activate_pull) {
- GST_DEBUG_OBJECT (basesink, "pull mode disabled");
- goto fallback;
- }
-
- /* check if downstreams supports pull mode at all */
- query = gst_query_new_scheduling ();
-
- if (!gst_pad_peer_query (pad, query)) {
- gst_query_unref (query);
- GST_DEBUG_OBJECT (basesink, "peer query failed, no pull mode");
- goto fallback;
- }
-
- /* parse result of the query */
- pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
- gst_query_unref (query);
-
- if (!pull_mode) {
- GST_DEBUG_OBJECT (basesink, "pull mode not supported");
- goto fallback;
- }
-
- /* set the pad mode before starting the task so that it's in the
- * correct state for the new thread. also the sink set_caps and get_caps
- * function checks this */
- basesink->pad_mode = GST_PAD_MODE_PULL;
-
- /* we first try to negotiate a format so that when we try to activate
- * downstream, it knows about our format */
- if (!gst_base_sink_negotiate_pull (basesink)) {
- GST_DEBUG_OBJECT (basesink, "failed to negotiate in pull mode");
- goto fallback;
- }
-
- /* ok activate now */
- if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) {
- /* clear any pending caps */
- GST_OBJECT_LOCK (basesink);
- gst_caps_replace (&basesink->priv->caps, NULL);
- GST_OBJECT_UNLOCK (basesink);
- GST_DEBUG_OBJECT (basesink, "failed to activate in pull mode");
- goto fallback;
- }
-
- GST_DEBUG_OBJECT (basesink, "Success activating pull mode");
- result = TRUE;
- goto done;
-
- /* push mode fallback */
-fallback:
- GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
- if ((result = gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE))) {
- GST_DEBUG_OBJECT (basesink, "Success activating push mode");
- }
-
-done:
- if (!result) {
- GST_WARNING_OBJECT (basesink, "Could not activate pad in either mode");
- gst_base_sink_set_flushing (basesink, pad, TRUE);
- }
-
- return result;
-}
-
-static gboolean
-gst_base_sink_pad_activate_push (GstPad * pad, GstObject * parent,
- gboolean active)
-{
- gboolean result;
- GstBaseSink *basesink;
-
- basesink = GST_BASE_SINK (parent);
-
- if (active) {
- if (!basesink->can_activate_push) {
- result = FALSE;
- basesink->pad_mode = GST_PAD_MODE_NONE;
- } else {
- result = TRUE;
- basesink->pad_mode = GST_PAD_MODE_PUSH;
- }
- } else {
- if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH)) {
- g_warning ("Internal GStreamer activation error!!!");
- result = FALSE;
- } else {
- gst_base_sink_set_flushing (basesink, pad, TRUE);
- result = TRUE;
- basesink->pad_mode = GST_PAD_MODE_NONE;
- }
- }
-
- return result;
-}
-
-static gboolean
-gst_base_sink_negotiate_pull (GstBaseSink * basesink)
-{
- GstCaps *caps;
- gboolean result;
-
- result = FALSE;
-
- /* this returns the intersection between our caps and the peer caps. If there
- * is no peer, it returns %NULL and we can't operate in pull mode so we can
- * fail the negotiation. */
- caps = gst_pad_get_allowed_caps (GST_BASE_SINK_PAD (basesink));
- if (caps == NULL || gst_caps_is_empty (caps))
- goto no_caps_possible;
-
- GST_DEBUG_OBJECT (basesink, "allowed caps: %" GST_PTR_FORMAT, caps);
-
- if (gst_caps_is_any (caps)) {
- GST_DEBUG_OBJECT (basesink, "caps were ANY after fixating, "
- "allowing pull()");
- /* neither side has template caps in this case, so they are prepared for
- pull() without setcaps() */
- result = TRUE;
- } else {
- /* try to fixate */
- caps = gst_base_sink_fixate (basesink, caps);
- GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
-
- if (gst_caps_is_fixed (caps)) {
- if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps))
- goto could_not_set_caps;
-
- result = TRUE;
- }
- }
-
- gst_caps_unref (caps);
-
- return result;
-
-no_caps_possible:
- {
- GST_INFO_OBJECT (basesink, "Pipeline could not agree on caps");
- GST_DEBUG_OBJECT (basesink, "get_allowed_caps() returned EMPTY");
- if (caps)
- gst_caps_unref (caps);
- return FALSE;
- }
-could_not_set_caps:
- {
- GST_INFO_OBJECT (basesink, "Could not set caps: %" GST_PTR_FORMAT, caps);
- gst_caps_unref (caps);
- return FALSE;
- }
-}
-
-/* this won't get called until we implement an activate function */
-static gboolean
-gst_base_sink_pad_activate_pull (GstPad * pad, GstObject * parent,
- gboolean active)
-{
- gboolean result = FALSE;
- GstBaseSink *basesink;
- GstBaseSinkClass *bclass;
-
- basesink = GST_BASE_SINK (parent);
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- if (active) {
- gint64 duration;
-
- /* we mark we have a newsegment here because pull based
- * mode works just fine without having a newsegment before the
- * first buffer */
- gst_segment_init (&basesink->segment, GST_FORMAT_BYTES);
- GST_OBJECT_LOCK (basesink);
- basesink->have_newsegment = TRUE;
- GST_OBJECT_UNLOCK (basesink);
-
- /* get the peer duration in bytes */
- result = gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &duration);
- if (result) {
- GST_DEBUG_OBJECT (basesink,
- "setting duration in bytes to %" G_GINT64_FORMAT, duration);
- basesink->segment.duration = duration;
- } else {
- GST_DEBUG_OBJECT (basesink, "unknown duration");
- }
-
- if (bclass->activate_pull)
- result = bclass->activate_pull (basesink, TRUE);
- else
- result = FALSE;
-
- if (!result)
- goto activate_failed;
-
- } else {
- if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PULL)) {
- g_warning ("Internal GStreamer activation error!!!");
- result = FALSE;
- } else {
- result = gst_base_sink_set_flushing (basesink, pad, TRUE);
- if (bclass->activate_pull)
- result &= bclass->activate_pull (basesink, FALSE);
- basesink->pad_mode = GST_PAD_MODE_NONE;
- }
- }
-
- return result;
-
- /* ERRORS */
-activate_failed:
- {
- /* reset, as starting the thread failed */
- basesink->pad_mode = GST_PAD_MODE_NONE;
-
- GST_ERROR_OBJECT (basesink, "subclass failed to activate in pull mode");
- return FALSE;
- }
-}
-
-static gboolean
-gst_base_sink_pad_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active)
-{
- gboolean res;
-
- switch (mode) {
- case GST_PAD_MODE_PULL:
- res = gst_base_sink_pad_activate_pull (pad, parent, active);
- break;
- case GST_PAD_MODE_PUSH:
- res = gst_base_sink_pad_activate_push (pad, parent, active);
- break;
- default:
- GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
- res = FALSE;
- break;
- }
- return res;
-}
-
-/* send an event to our sinkpad peer. */
-static gboolean
-gst_base_sink_send_event (GstElement * element, GstEvent * event)
-{
- GstPad *pad;
- GstBaseSink *basesink = GST_BASE_SINK (element);
- gboolean forward, result = TRUE;
- GstPadMode mode;
-
- GST_OBJECT_LOCK (element);
- /* get the pad and the scheduling mode */
- pad = gst_object_ref (basesink->sinkpad);
- mode = basesink->pad_mode;
- GST_OBJECT_UNLOCK (element);
-
- /* only push UPSTREAM events upstream */
- forward = GST_EVENT_IS_UPSTREAM (event);
-
- GST_DEBUG_OBJECT (basesink, "handling event %p %" GST_PTR_FORMAT, event,
- event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_LATENCY:
- {
- GstClockTime latency;
-
- gst_event_parse_latency (event, &latency);
-
- /* store the latency. We use this to adjust the running_time before syncing
- * it to the clock. */
- GST_OBJECT_LOCK (element);
- basesink->priv->latency = latency;
- if (!basesink->priv->have_latency)
- forward = FALSE;
- GST_OBJECT_UNLOCK (element);
- GST_DEBUG_OBJECT (basesink, "latency set to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (latency));
-
- /* We forward this event so that all elements know about the global pipeline
- * latency. This is interesting for an element when it wants to figure out
- * when a particular piece of data will be rendered. */
- break;
- }
- case GST_EVENT_INSTANT_RATE_SYNC_TIME:
- {
- gst_base_sink_perform_instant_rate_change (basesink, pad, event);
-
- /* Forward the event. If upstream handles it already, it is supposed to
- * send a SEGMENT event with the same seqnum and the final rate before
- * the next buffer
- */
- forward = TRUE;
-
- break;
- }
- case GST_EVENT_SEEK:
- /* in pull mode we will execute the seek */
- if (mode == GST_PAD_MODE_PULL)
- result = gst_base_sink_perform_seek (basesink, pad, event);
- break;
- case GST_EVENT_STEP:
- result = gst_base_sink_perform_step (basesink, pad, event);
- forward = FALSE;
- break;
- default:
- break;
- }
-
- if (forward) {
- GST_DEBUG_OBJECT (basesink, "sending event %p %" GST_PTR_FORMAT, event,
- event);
-
- /* Compensate for any instant-rate-change related running time offset
- * between upstream and the internal running time of the sink */
- if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
- GstClockTime now = GST_CLOCK_TIME_NONE;
- GstClockTime actual_duration;
- GstClockTime upstream_duration;
- GstClockTimeDiff difference;
- gboolean is_playing, negative_duration;
-
- GST_OBJECT_LOCK (basesink);
- is_playing = GST_STATE (basesink) == GST_STATE_PLAYING
- && (GST_STATE_PENDING (basesink) == GST_STATE_VOID_PENDING ||
- GST_STATE_PENDING (basesink) == GST_STATE_PLAYING);
-
- if (is_playing) {
- GstClockTime base_time, clock_time;
- GstClock *clock;
-
- base_time = GST_ELEMENT_CAST (basesink)->base_time;
- clock = GST_ELEMENT_CLOCK (basesink);
- GST_OBJECT_UNLOCK (basesink);
-
- if (clock) {
- clock_time = gst_clock_get_time (clock);
- now = clock_time - base_time;
- }
- } else {
- now = GST_ELEMENT_START_TIME (basesink);
- GST_OBJECT_UNLOCK (basesink);
- }
-
- GST_DEBUG_OBJECT (basesink,
- "Current internal running time %" GST_TIME_FORMAT
- ", last internal running time %" GST_TIME_FORMAT, GST_TIME_ARGS (now),
- GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
-
- if (now != GST_CLOCK_TIME_NONE) {
- /* Calculate how much running time was spent since the last switch/segment
- * in the "corrected upstream segment", our segment */
- /* Due to rounding errors and other inaccuracies, it can happen
- * that our calculated internal running time is before the upstream
- * running time. We need to compensate for that */
- if (now < basesink->priv->last_anchor_running_time) {
- actual_duration = basesink->priv->last_anchor_running_time - now;
- negative_duration = TRUE;
- } else {
- actual_duration = now - basesink->priv->last_anchor_running_time;
- negative_duration = FALSE;
- }
-
- /* Transpose that duration (i.e. what upstream beliefs) */
- upstream_duration =
- (actual_duration * basesink->segment.rate) /
- basesink->priv->upstream_segment.rate;
-
- /* Add the difference to the previously accumulated correction */
- if (negative_duration)
- difference = upstream_duration - actual_duration;
- else
- difference = actual_duration - upstream_duration;
-
- GST_DEBUG_OBJECT (basesink,
- "Current instant rate correction offset. Actual duration %"
- GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
- ", negative %d, difference %" GST_STIME_FORMAT ", current offset %"
- GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
- GST_TIME_ARGS (upstream_duration), negative_duration,
- GST_STIME_ARGS (difference),
- GST_STIME_ARGS (basesink->priv->instant_rate_offset + difference));
-
- difference = basesink->priv->instant_rate_offset + difference;
-
- event = gst_event_make_writable (event);
- gst_event_set_running_time_offset (event, -difference);
- }
- }
-
- result = gst_pad_push_event (pad, event);
- } else {
- /* not forwarded, unref the event */
- gst_event_unref (event);
- }
-
- gst_object_unref (pad);
-
- GST_DEBUG_OBJECT (basesink, "handled event: %d", result);
-
- return result;
-}
-
-static gboolean
-gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
- gint64 * cur, gboolean * upstream)
-{
- GstClock *clock = NULL;
- gboolean res = FALSE;
- GstFormat oformat;
- GstSegment *segment;
- GstClockTime now, latency;
- GstClockTimeDiff base_time;
- gint64 time, base, offset, duration;
- gdouble rate;
- gint64 last;
- gboolean last_seen, with_clock, in_paused;
-
- GST_OBJECT_LOCK (basesink);
- /* we can only get the segment when we are not NULL or READY */
- if (!basesink->have_newsegment)
- goto wrong_state;
-
- in_paused = FALSE;
- /* when not in PLAYING or when we're busy with a state change, we
- * cannot read from the clock so we report time based on the
- * last seen timestamp. */
- if (GST_STATE (basesink) != GST_STATE_PLAYING ||
- GST_STATE_PENDING (basesink) != GST_STATE_VOID_PENDING) {
- in_paused = TRUE;
- }
-
- segment = &basesink->segment;
-
- /* get the format in the segment */
- oformat = segment->format;
-
- /* report with last seen position when EOS */
- last_seen = basesink->eos;
-
- /* assume we will use the clock for getting the current position */
- with_clock = TRUE;
- if (!basesink->sync)
- with_clock = FALSE;
-
- /* and we need a clock */
- if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL))
- with_clock = FALSE;
- else
- gst_object_ref (clock);
-
- /* mainloop might be querying position when going to playing async,
- * while (audio) rendering might be quickly advancing stream position,
- * so use clock asap rather than last reported position */
- if (in_paused && with_clock && g_atomic_int_get (&basesink->priv->to_playing)) {
- GST_DEBUG_OBJECT (basesink, "going to PLAYING, so not PAUSED");
- in_paused = FALSE;
- }
-
- /* collect all data we need holding the lock */
- if (GST_CLOCK_TIME_IS_VALID (segment->time))
- time = segment->time;
- else
- time = 0;
-
- if (GST_CLOCK_TIME_IS_VALID (segment->offset))
- offset = segment->offset;
- else
- offset = 0;
-
- if (GST_CLOCK_TIME_IS_VALID (segment->stop))
- duration = segment->stop - segment->start;
- else
- duration = 0;
-
- base = segment->base;
- rate = segment->rate * segment->applied_rate;
- latency = basesink->priv->latency;
-
- if (in_paused) {
- /* in paused, use start_time */
- base_time = GST_ELEMENT_START_TIME (basesink);
- GST_DEBUG_OBJECT (basesink, "in paused, using start time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (base_time));
- } else if (with_clock) {
- /* else use clock when needed */
- base_time = GST_ELEMENT_CAST (basesink)->base_time;
- GST_DEBUG_OBJECT (basesink, "using clock and base time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (base_time));
- } else {
- /* else, no sync or clock -> no base time */
- GST_DEBUG_OBJECT (basesink, "no sync or no clock");
- base_time = -1;
- }
-
- /* no base_time, we can't calculate running_time, use last seem timestamp to report
- * time */
- if (base_time == -1)
- last_seen = TRUE;
-
- if (oformat == GST_FORMAT_TIME) {
- gint64 start, stop;
-
- start = basesink->priv->current_sstart;
- stop = basesink->priv->current_sstop;
-
- if (last_seen) {
- /* when we don't use the clock, we use the last position as a lower bound */
- if (stop == -1 || segment->rate > 0.0)
- last = start;
- else
- last = stop;
-
- GST_DEBUG_OBJECT (basesink, "in PAUSED using last %" GST_TIME_FORMAT,
- GST_TIME_ARGS (last));
- } else {
- /* in playing and paused, use last stop time as upper bound */
- if (start == -1 || segment->rate > 0.0)
- last = stop;
- else
- last = start;
-
- GST_DEBUG_OBJECT (basesink, "in PLAYING using last %" GST_TIME_FORMAT,
- GST_TIME_ARGS (last));
- }
- } else {
- /* convert position to stream time */
- last = gst_segment_to_stream_time (segment, oformat, segment->position);
-
- GST_DEBUG_OBJECT (basesink, "in using last %" G_GINT64_FORMAT, last);
- }
-
- /* need to release the object lock before we can get the time,
- * a clock might take the LOCK of the provider, which could be
- * a basesink subclass. */
- GST_OBJECT_UNLOCK (basesink);
-
- if (last_seen) {
- /* in EOS or when no valid stream_time, report the value of last seen
- * timestamp */
- if (last == -1) {
- /* no timestamp, we need to ask upstream */
- GST_DEBUG_OBJECT (basesink, "no last seen timestamp, asking upstream");
- res = FALSE;
- *upstream = TRUE;
- goto done;
- }
- GST_DEBUG_OBJECT (basesink, "using last seen timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (last));
- *cur = last;
- } else {
- if (oformat != GST_FORMAT_TIME) {
- /* convert base, time and duration to time */
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, base,
- GST_FORMAT_TIME, &base))
- goto convert_failed;
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, duration,
- GST_FORMAT_TIME, &duration))
- goto convert_failed;
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, time,
- GST_FORMAT_TIME, &time))
- goto convert_failed;
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, last,
- GST_FORMAT_TIME, &last))
- goto convert_failed;
-
- /* assume time format from now on */
- oformat = GST_FORMAT_TIME;
- }
-
- if (!in_paused && with_clock) {
- now = gst_clock_get_time (clock);
- } else {
- now = base_time;
- base_time = 0;
- }
-
- /* subtract base time and base time from the clock time.
- * Make sure we don't go negative. This is the current time in
- * the segment which we need to scale with the combined
- * rate and applied rate. */
- base_time += base;
- base_time += latency;
- if (GST_CLOCK_DIFF (base_time, now) < 0)
- base_time = now;
-
- /* for negative rates we need to count back from the segment
- * duration. */
- if (rate < 0.0)
- time += duration;
-
- *cur = time + offset + gst_guint64_to_gdouble (now - base_time) * rate;
-
- /* never report more than last seen position */
- if (last != -1) {
- if (rate > 0.0)
- *cur = MIN (last, *cur);
- else
- *cur = MAX (last, *cur);
- }
-
- GST_DEBUG_OBJECT (basesink,
- "now %" GST_TIME_FORMAT " - base_time %" GST_TIME_FORMAT " - base %"
- GST_TIME_FORMAT " + time %" GST_TIME_FORMAT " last %" GST_TIME_FORMAT,
- GST_TIME_ARGS (now), GST_TIME_ARGS (base_time), GST_TIME_ARGS (base),
- GST_TIME_ARGS (time), GST_TIME_ARGS (last));
- }
-
- if (oformat != format) {
- /* convert to final format */
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, format, cur))
- goto convert_failed;
- }
-
- res = TRUE;
-
-done:
- GST_DEBUG_OBJECT (basesink, "res: %d, POSITION: %" GST_TIME_FORMAT,
- res, GST_TIME_ARGS (*cur));
-
- if (clock)
- gst_object_unref (clock);
-
- return res;
-
- /* special cases */
-wrong_state:
- {
- /* in NULL or READY we always return FALSE and -1 */
- GST_DEBUG_OBJECT (basesink, "position in wrong state, return -1");
- res = FALSE;
- *cur = -1;
- GST_OBJECT_UNLOCK (basesink);
- goto done;
- }
-convert_failed:
- {
- GST_DEBUG_OBJECT (basesink, "convert failed, try upstream");
- *upstream = TRUE;
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-gst_base_sink_get_duration (GstBaseSink * basesink, GstFormat format,
- gint64 * dur, gboolean * upstream)
-{
- gboolean res = FALSE;
-
- if (basesink->pad_mode == GST_PAD_MODE_PULL) {
- gint64 uduration;
-
- /* get the duration in bytes, in pull mode that's all we are sure to
- * know. We have to explicitly get this value from upstream instead of
- * using our cached value because it might change. Duration caching
- * should be done at a higher level. */
- res =
- gst_pad_peer_query_duration (basesink->sinkpad, GST_FORMAT_BYTES,
- &uduration);
- if (res) {
- basesink->segment.duration = uduration;
- if (format != GST_FORMAT_BYTES) {
- /* convert to the requested format */
- res =
- gst_pad_query_convert (basesink->sinkpad, GST_FORMAT_BYTES,
- uduration, format, dur);
- } else {
- *dur = uduration;
- }
- }
- *upstream = FALSE;
- } else {
- *upstream = TRUE;
- }
-
- return res;
-}
-
-static gboolean
-default_element_query (GstElement * element, GstQuery * query)
-{
- gboolean res = FALSE;
-
- GstBaseSink *basesink = GST_BASE_SINK (element);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 cur = 0;
- GstFormat format;
- gboolean upstream = FALSE;
-
- gst_query_parse_position (query, &format, NULL);
-
- GST_DEBUG_OBJECT (basesink, "position query in format %s",
- gst_format_get_name (format));
-
- /* first try to get the position based on the clock */
- if ((res =
- gst_base_sink_get_position (basesink, format, &cur, &upstream))) {
- gst_query_set_position (query, format, cur);
- } else if (upstream) {
- /* fallback to peer query */
- res = gst_pad_peer_query (basesink->sinkpad, query);
- }
- if (!res) {
- /* we can handle a few things if upstream failed */
- if (format == GST_FORMAT_PERCENT) {
- gint64 dur = 0;
-
- res = gst_base_sink_get_position (basesink, GST_FORMAT_TIME, &cur,
- &upstream);
- if (!res && upstream) {
- res =
- gst_pad_peer_query_position (basesink->sinkpad, GST_FORMAT_TIME,
- &cur);
- }
- if (res) {
- res = gst_base_sink_get_duration (basesink, GST_FORMAT_TIME, &dur,
- &upstream);
- if (!res && upstream) {
- res =
- gst_pad_peer_query_duration (basesink->sinkpad,
- GST_FORMAT_TIME, &dur);
- }
- }
- if (res) {
- gint64 pos;
-
- pos = gst_util_uint64_scale (100 * GST_FORMAT_PERCENT_SCALE, cur,
- dur);
- gst_query_set_position (query, GST_FORMAT_PERCENT, pos);
- }
- }
- }
- break;
- }
- case GST_QUERY_DURATION:
- {
- gint64 dur = 0;
- GstFormat format;
- gboolean upstream = FALSE;
-
- gst_query_parse_duration (query, &format, NULL);
-
- GST_DEBUG_OBJECT (basesink, "duration query in format %s",
- gst_format_get_name (format));
-
- if ((res =
- gst_base_sink_get_duration (basesink, format, &dur, &upstream))) {
- gst_query_set_duration (query, format, dur);
- } else if (upstream) {
- /* fallback to peer query */
- res = gst_pad_peer_query (basesink->sinkpad, query);
- }
- if (!res) {
- /* we can handle a few things if upstream failed */
- if (format == GST_FORMAT_PERCENT) {
- gst_query_set_duration (query, GST_FORMAT_PERCENT,
- GST_FORMAT_PERCENT_MAX);
- res = TRUE;
- }
- }
- break;
- }
- case GST_QUERY_LATENCY:
- {
- gboolean live, us_live;
- GstClockTime min, max;
-
- if ((res = gst_base_sink_query_latency (basesink, &live, &us_live, &min,
- &max))) {
- gst_query_set_latency (query, live, min, max);
- }
- break;
- }
- case GST_QUERY_JITTER:
- break;
- case GST_QUERY_RATE:
- /* gst_query_set_rate (query, basesink->segment_rate); */
- res = TRUE;
- break;
- case GST_QUERY_SEGMENT:
- {
- if (basesink->pad_mode == GST_PAD_MODE_PULL) {
- GstFormat format;
- gint64 start, stop;
-
- format = basesink->segment.format;
-
- start =
- gst_segment_to_stream_time (&basesink->segment, format,
- basesink->segment.start);
- if ((stop = basesink->segment.stop) == -1)
- stop = basesink->segment.duration;
- else
- stop = gst_segment_to_stream_time (&basesink->segment, format, stop);
-
- gst_query_set_segment (query, basesink->segment.rate, format, start,
- stop);
- res = TRUE;
- } else {
- res = gst_pad_peer_query (basesink->sinkpad, query);
- }
- break;
- }
- case GST_QUERY_SEEKING:
- case GST_QUERY_CONVERT:
- case GST_QUERY_FORMATS:
- default:
- res = gst_pad_peer_query (basesink->sinkpad, query);
- break;
- }
- GST_DEBUG_OBJECT (basesink, "query %s returns %d",
- GST_QUERY_TYPE_NAME (query), res);
- return res;
-}
-
-static void
-gst_base_sink_drain (GstBaseSink * basesink)
-{
- GstBuffer *old;
- GstBufferList *old_list;
-
- GST_OBJECT_LOCK (basesink);
- if ((old = basesink->priv->last_buffer))
- basesink->priv->last_buffer = gst_buffer_copy_deep (old);
-
- if ((old_list = basesink->priv->last_buffer_list))
- basesink->priv->last_buffer_list = gst_buffer_list_copy_deep (old_list);
- GST_OBJECT_UNLOCK (basesink);
-
- if (old)
- gst_buffer_unref (old);
- if (old_list)
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (old_list));
-}
-
-static gboolean
-gst_base_sink_default_query (GstBaseSink * basesink, GstQuery * query)
-{
- gboolean res;
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_ALLOCATION:
- {
- gst_base_sink_drain (basesink);
- if (bclass->propose_allocation)
- res = bclass->propose_allocation (basesink, query);
- else
- res = FALSE;
- break;
- }
- case GST_QUERY_CAPS:
- {
- GstCaps *caps, *filter;
-
- gst_query_parse_caps (query, &filter);
- caps = gst_base_sink_query_caps (basesink, basesink->sinkpad, filter);
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- res = TRUE;
- break;
- }
- case GST_QUERY_ACCEPT_CAPS:
- {
- GstCaps *caps, *allowed;
- gboolean subset;
-
- /* slightly faster than the default implementation */
- gst_query_parse_accept_caps (query, &caps);
- allowed = gst_base_sink_query_caps (basesink, basesink->sinkpad, NULL);
- subset = gst_caps_is_subset (caps, allowed);
- GST_DEBUG_OBJECT (basesink, "Checking if requested caps %" GST_PTR_FORMAT
- " are a subset of pad caps %" GST_PTR_FORMAT " result %d", caps,
- allowed, subset);
- gst_caps_unref (allowed);
- gst_query_set_accept_caps_result (query, subset);
- res = TRUE;
- break;
- }
- case GST_QUERY_DRAIN:
- {
- gst_base_sink_drain (basesink);
- res = TRUE;
- break;
- }
- case GST_QUERY_POSITION:
- {
- res = default_element_query (GST_ELEMENT (basesink), query);
- break;
- }
- default:
- res =
- gst_pad_query_default (basesink->sinkpad, GST_OBJECT_CAST (basesink),
- query);
- break;
- }
- return res;
-}
-
-static gboolean
-gst_base_sink_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstBaseSink *basesink;
- GstBaseSinkClass *bclass;
- gboolean res;
-
- basesink = GST_BASE_SINK_CAST (parent);
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- if (bclass->query)
- res = bclass->query (basesink, query);
- else
- res = FALSE;
-
- return res;
-}
-
-static GstStateChangeReturn
-gst_base_sink_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstBaseSink *basesink = GST_BASE_SINK (element);
- GstBaseSinkClass *bclass;
- GstBaseSinkPrivate *priv;
-
- priv = basesink->priv;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (bclass->start)
- if (!bclass->start (basesink))
- goto start_failed;
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- /* need to complete preroll before this state change completes, there
- * is no data flow in READY so we can safely assume we need to preroll. */
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- GST_DEBUG_OBJECT (basesink, "READY to PAUSED");
- basesink->have_newsegment = FALSE;
- gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
- gst_segment_init (&basesink->priv->upstream_segment,
- GST_FORMAT_UNDEFINED);
- basesink->offset = 0;
- basesink->have_preroll = FALSE;
- priv->step_unlock = FALSE;
- basesink->need_preroll = TRUE;
- basesink->playing_async = TRUE;
- priv->current_sstart = GST_CLOCK_TIME_NONE;
- priv->current_sstop = GST_CLOCK_TIME_NONE;
- priv->eos_rtime = GST_CLOCK_TIME_NONE;
- priv->latency = 0;
- basesink->eos = FALSE;
- priv->received_eos = FALSE;
- gst_base_sink_reset_qos (basesink);
- priv->rc_next = -1;
- priv->committed = FALSE;
- priv->call_preroll = TRUE;
- priv->current_step.valid = FALSE;
- priv->pending_step.valid = FALSE;
- priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
- priv->instant_rate_multiplier = 0;
- priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
- priv->segment_seqnum = GST_SEQNUM_INVALID;
- priv->instant_rate_offset = 0;
- priv->last_anchor_running_time = 0;
- if (priv->async_enabled) {
- GST_DEBUG_OBJECT (basesink, "doing async state change");
- /* when async enabled, post async-start message and return ASYNC from
- * the state change function */
- ret = GST_STATE_CHANGE_ASYNC;
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
- } else {
- priv->have_latency = TRUE;
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_latency (GST_OBJECT_CAST (basesink)));
- }
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- g_atomic_int_set (&basesink->priv->to_playing, TRUE);
- if (!gst_base_sink_needs_preroll (basesink)) {
- GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, don't need preroll");
- /* no preroll needed anymore now. */
- basesink->playing_async = FALSE;
- basesink->need_preroll = FALSE;
- if (basesink->eos) {
- GstMessage *message;
-
- /* need to post EOS message here */
- GST_DEBUG_OBJECT (basesink, "Now posting EOS");
- message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
- gst_message_set_seqnum (message, basesink->priv->seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
- } else {
- GST_DEBUG_OBJECT (basesink, "signal preroll");
- GST_BASE_SINK_PREROLL_SIGNAL (basesink);
- }
- } else {
- GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled");
- basesink->need_preroll = TRUE;
- basesink->playing_async = TRUE;
- priv->call_preroll = TRUE;
- priv->committed = FALSE;
- if (priv->async_enabled) {
- GST_DEBUG_OBJECT (basesink, "doing async state change");
- ret = GST_STATE_CHANGE_ASYNC;
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
- }
- }
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- break;
- default:
- break;
- }
-
- {
- GstStateChangeReturn bret;
-
- bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE))
- goto activate_failed;
- }
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- /* completed transition, so need not be marked any longer
- * And it should be unmarked, since e.g. losing our position upon flush
- * does not really change state to PAUSED ... */
- g_atomic_int_set (&basesink->priv->to_playing, FALSE);
- break;
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- g_atomic_int_set (&basesink->priv->to_playing, FALSE);
- GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED");
- /* FIXME, make sure we cannot enter _render first */
-
- /* we need to call ::unlock before locking PREROLL_LOCK
- * since we lock it before going into ::render */
- if (bclass->unlock)
- bclass->unlock (basesink);
-
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- GST_DEBUG_OBJECT (basesink, "got preroll lock");
- /* now that we have the PREROLL lock, clear our unlock request */
- if (bclass->unlock_stop)
- bclass->unlock_stop (basesink);
-
- if (basesink->clock_id) {
- GST_DEBUG_OBJECT (basesink, "unschedule clock");
- gst_clock_id_unschedule (basesink->clock_id);
- }
-
- /* if we don't have a preroll buffer we need to wait for a preroll and
- * return ASYNC. */
- if (!gst_base_sink_needs_preroll (basesink)) {
- GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED, we are prerolled");
- basesink->playing_async = FALSE;
- basesink->need_preroll = FALSE;
- } else {
- if (GST_STATE_TARGET (GST_ELEMENT (basesink)) <= GST_STATE_READY) {
- GST_DEBUG_OBJECT (basesink, "element is <= READY");
- ret = GST_STATE_CHANGE_SUCCESS;
- } else {
- GST_DEBUG_OBJECT (basesink,
- "PLAYING to PAUSED, we are not prerolled");
- basesink->playing_async = TRUE;
- basesink->need_preroll = TRUE;
- priv->committed = FALSE;
- priv->call_preroll = TRUE;
- if (priv->async_enabled) {
- GST_DEBUG_OBJECT (basesink, "doing async state change");
- ret = GST_STATE_CHANGE_ASYNC;
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
- }
- }
- }
- GST_DEBUG_OBJECT (basesink, "rendered: %" G_GUINT64_FORMAT
- ", dropped: %" G_GUINT64_FORMAT, priv->rendered, priv->dropped);
-
- gst_base_sink_reset_qos (basesink);
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_BASE_SINK_PREROLL_LOCK (basesink);
- /* start by resetting our position state with the object lock so that the
- * position query gets the right idea. We do this before we post the
- * messages so that the message handlers pick this up. */
- GST_OBJECT_LOCK (basesink);
- basesink->have_newsegment = FALSE;
- priv->current_sstart = GST_CLOCK_TIME_NONE;
- priv->current_sstop = GST_CLOCK_TIME_NONE;
- priv->have_latency = FALSE;
- if (priv->cached_clock_id) {
- gst_clock_id_unref (priv->cached_clock_id);
- priv->cached_clock_id = NULL;
- }
- gst_caps_replace (&basesink->priv->caps, NULL);
- GST_OBJECT_UNLOCK (basesink);
-
- gst_base_sink_set_last_buffer (basesink, NULL);
- gst_base_sink_set_last_buffer_list (basesink, NULL);
- priv->call_preroll = FALSE;
-
- if (!priv->committed) {
- if (priv->async_enabled) {
- GST_DEBUG_OBJECT (basesink, "PAUSED to READY, posting async-done");
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_state_changed (GST_OBJECT_CAST (basesink),
- GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY));
-
- gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_done (GST_OBJECT_CAST (basesink),
- GST_CLOCK_TIME_NONE));
- }
- priv->committed = TRUE;
- } else {
- GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll");
- }
- GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- if (bclass->stop) {
- if (!bclass->stop (basesink)) {
- GST_WARNING_OBJECT (basesink, "failed to stop");
- }
- }
- gst_base_sink_set_last_buffer (basesink, NULL);
- gst_base_sink_set_last_buffer_list (basesink, NULL);
- priv->call_preroll = FALSE;
- break;
- default:
- break;
- }
-
- return ret;
-
- /* ERRORS */
-start_failed:
- {
- GST_DEBUG_OBJECT (basesink, "failed to start");
- /* subclass is supposed to post a message but we post one as a fallback
- * just in case */
- GST_ELEMENT_ERROR (basesink, CORE, STATE_CHANGE, (NULL),
- ("Failed to start"));
- return GST_STATE_CHANGE_FAILURE;
- }
-activate_failed:
- {
- GST_DEBUG_OBJECT (basesink,
- "element failed to change states -- activation problem?");
- return GST_STATE_CHANGE_FAILURE;
- }
-}
-
-/**
- * gst_base_sink_get_stats:
- * @sink: #GstBaseSink
- *
- * Return various #GstBaseSink statistics. This function returns a #GstStructure
- * with name `application/x-gst-base-sink-stats` with the following fields:
- *
- * - "average-rate" G_TYPE_DOUBLE average frame rate
- * - "dropped" G_TYPE_UINT64 Number of dropped frames
- * - "rendered" G_TYPE_UINT64 Number of rendered frames
- *
- * Returns: (transfer full): pointer to #GstStructure
- *
- * Since: 1.18
- */
-GstStructure *
-gst_base_sink_get_stats (GstBaseSink * sink)
-{
- GstBaseSinkPrivate *priv = NULL;
-
- g_return_val_if_fail (sink != NULL, NULL);
- priv = sink->priv;
- return gst_structure_new ("application/x-gst-base-sink-stats",
- "average-rate", G_TYPE_DOUBLE, priv->avg_rate,
- "dropped", G_TYPE_UINT64, priv->dropped,
- "rendered", G_TYPE_UINT64, priv->rendered, NULL);
-}
diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h
deleted file mode 100644
index 3745fa20ab..0000000000
--- a/libs/gst/base/gstbasesink.h
+++ /dev/null
@@ -1,339 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_SINK_H__
-#define __GST_BASE_SINK_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.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(klass) (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)
-
-#define GST_BASE_SINK_GET_PREROLL_LOCK(obj) (&GST_BASE_SINK_CAST(obj)->preroll_lock)
-#define GST_BASE_SINK_PREROLL_LOCK(obj) (g_mutex_lock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
-#define GST_BASE_SINK_PREROLL_TRYLOCK(obj) (g_mutex_trylock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
-#define GST_BASE_SINK_PREROLL_UNLOCK(obj) (g_mutex_unlock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
-
-#define GST_BASE_SINK_GET_PREROLL_COND(obj) (&GST_BASE_SINK_CAST(obj)->preroll_cond)
-#define GST_BASE_SINK_PREROLL_WAIT(obj) \
- g_cond_wait (GST_BASE_SINK_GET_PREROLL_COND (obj), GST_BASE_SINK_GET_PREROLL_LOCK (obj))
-#define GST_BASE_SINK_PREROLL_WAIT_UNTIL(obj, end_time) \
- g_cond_wait_until (GST_BASE_SINK_GET_PREROLL_COND (obj), GST_BASE_SINK_GET_PREROLL_LOCK (obj), end_time)
-#define GST_BASE_SINK_PREROLL_SIGNAL(obj) g_cond_signal (GST_BASE_SINK_GET_PREROLL_COND (obj));
-#define GST_BASE_SINK_PREROLL_BROADCAST(obj) g_cond_broadcast (GST_BASE_SINK_GET_PREROLL_COND (obj));
-
-typedef struct _GstBaseSink GstBaseSink;
-typedef struct _GstBaseSinkClass GstBaseSinkClass;
-typedef struct _GstBaseSinkPrivate GstBaseSinkPrivate;
-
-/**
- * GstBaseSink:
- *
- * The opaque #GstBaseSink data structure.
- */
-struct _GstBaseSink {
- GstElement element;
-
- /*< protected >*/
- GstPad *sinkpad;
- GstPadMode pad_mode;
-
- /*< protected >*/ /* with LOCK */
- guint64 offset;
- gboolean can_activate_pull;
- gboolean can_activate_push;
-
- /*< protected >*/ /* with PREROLL_LOCK */
- GMutex preroll_lock;
- GCond preroll_cond;
- gboolean eos;
- gboolean need_preroll;
- gboolean have_preroll;
- gboolean playing_async;
-
- /*< protected >*/ /* with STREAM_LOCK */
- gboolean have_newsegment;
- GstSegment segment;
-
- /*< private >*/ /* with LOCK */
- GstClockID clock_id;
- gboolean sync;
- gboolean flushing;
- gboolean running;
-
- gint64 max_lateness;
-
- /*< private >*/
- GstBaseSinkPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-/**
- * GstBaseSinkClass:
- * @parent_class: Element parent class
- * @get_caps: Called to get sink pad caps from the subclass
- * @set_caps: Notify subclass of changed caps
- * @fixate: Only useful in pull mode. Implement if you have
- * ideas about what should be the default values for the caps you support.
- * @activate_pull: Subclasses should override this when they can provide an
- * alternate method of spawning a thread to drive the pipeline in pull mode.
- * Should start or stop the pulling thread, depending on the value of the
- * "active" argument. Called after actually activating the sink pad in pull
- * mode. The default implementation starts a task on the sink pad.
- * @get_times: Called to get the start and end times for synchronising
- * the passed buffer to the clock
- * @propose_allocation: configure the allocation query
- * @start: Start processing. Ideal for opening resources in the subclass
- * @stop: Stop processing. Subclasses should use this to close resources.
- * @unlock: Unlock any pending access to the resource. Subclasses should
- * unblock any blocked function ASAP and call gst_base_sink_wait_preroll()
- * @unlock_stop: Clear the previous unlock request. Subclasses should clear
- * any state they set during #GstBaseSinkClass::unlock, and be ready to
- * continue where they left off after gst_base_sink_wait_preroll(),
- * gst_base_sink_wait() or gst_wait_sink_wait_clock() return or
- * #GstBaseSinkClass::render is called again.
- * @query: perform a #GstQuery on the element.
- * @event: Override this to handle events arriving on the sink pad
- * @wait_event: Override this to implement custom logic to wait for the event
- * time (for events like EOS and GAP). Subclasses should always first
- * chain up to the default implementation.
- * @prepare: Called to prepare the buffer for @render and @preroll. This
- * function is called before synchronisation is performed.
- * @prepare_list: Called to prepare the buffer list for @render_list. This
- * function is called before synchronisation is performed.
- * @preroll: Called to present the preroll buffer if desired.
- * @render: Called when a buffer should be presented or output, at the
- * correct moment if the #GstBaseSink has been set to sync to the clock.
- * @render_list: Same as @render but used with buffer lists instead of
- * buffers.
- *
- * Subclasses can override any of the available virtual methods or not, as
- * needed. At the minimum, the @render method should be overridden to
- * output/present buffers.
- */
-struct _GstBaseSinkClass {
- GstElementClass parent_class;
-
- /**
- * GstBaseSink::get_caps:
- * @filter: (in) (nullable):
- *
- * Called to get sink pad caps from the subclass.
- */
- GstCaps* (*get_caps) (GstBaseSink *sink, GstCaps *filter);
- /* notify subclass of new caps */
- gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps);
-
- /* fixate sink caps during pull-mode negotiation */
- GstCaps * (*fixate) (GstBaseSink *sink, GstCaps *caps);
- /* start or stop a pulling thread */
- gboolean (*activate_pull)(GstBaseSink *sink, gboolean active);
-
- /* get the start and end times for syncing on this buffer */
- void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
- GstClockTime *start, GstClockTime *end);
-
- /* propose allocation parameters for upstream */
- gboolean (*propose_allocation) (GstBaseSink *sink, GstQuery *query);
-
- /* 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);
- /* Clear a previously indicated unlock request not that unlocking is
- * complete. Sub-classes should clear any command queue or indicator they
- * set during unlock */
- gboolean (*unlock_stop) (GstBaseSink *sink);
-
- /* notify subclass of query */
- gboolean (*query) (GstBaseSink *sink, GstQuery *query);
-
- /* notify subclass of event */
- gboolean (*event) (GstBaseSink *sink, GstEvent *event);
- /* wait for eos or gap, subclasses should chain up to parent first */
- GstFlowReturn (*wait_event) (GstBaseSink *sink, GstEvent *event);
-
- /* notify subclass of buffer or list before doing sync */
- GstFlowReturn (*prepare) (GstBaseSink *sink, GstBuffer *buffer);
- GstFlowReturn (*prepare_list) (GstBaseSink *sink, GstBufferList *buffer_list);
-
- /* notify subclass of preroll buffer or real buffer */
- GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
- GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);
- /* Render a BufferList */
- GstFlowReturn (*render_list) (GstBaseSink *sink, GstBufferList *buffer_list);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-GST_BASE_API
-GType gst_base_sink_get_type (void);
-
-GST_BASE_API
-GstFlowReturn gst_base_sink_do_preroll (GstBaseSink *sink, GstMiniObject *obj);
-
-GST_BASE_API
-GstFlowReturn gst_base_sink_wait_preroll (GstBaseSink *sink);
-
-/* synchronizing against the clock */
-
-GST_BASE_API
-void gst_base_sink_set_sync (GstBaseSink *sink, gboolean sync);
-
-GST_BASE_API
-gboolean gst_base_sink_get_sync (GstBaseSink *sink);
-
-/* Drop buffers which are out of segment */
-
-GST_BASE_API
-void gst_base_sink_set_drop_out_of_segment (GstBaseSink *sink, gboolean drop_out_of_segment);
-
-GST_BASE_API
-gboolean gst_base_sink_get_drop_out_of_segment (GstBaseSink *sink);
-
-/* dropping late buffers */
-
-GST_BASE_API
-void gst_base_sink_set_max_lateness (GstBaseSink *sink, gint64 max_lateness);
-
-GST_BASE_API
-gint64 gst_base_sink_get_max_lateness (GstBaseSink *sink);
-
-/* performing QoS */
-
-GST_BASE_API
-void gst_base_sink_set_qos_enabled (GstBaseSink *sink, gboolean enabled);
-
-GST_BASE_API
-gboolean gst_base_sink_is_qos_enabled (GstBaseSink *sink);
-
-/* doing async state changes */
-
-GST_BASE_API
-void gst_base_sink_set_async_enabled (GstBaseSink *sink, gboolean enabled);
-
-GST_BASE_API
-gboolean gst_base_sink_is_async_enabled (GstBaseSink *sink);
-
-/* tuning synchronisation */
-
-GST_BASE_API
-void gst_base_sink_set_ts_offset (GstBaseSink *sink, GstClockTimeDiff offset);
-
-GST_BASE_API
-GstClockTimeDiff gst_base_sink_get_ts_offset (GstBaseSink *sink);
-
-/* last sample */
-
-GST_BASE_API
-GstSample * gst_base_sink_get_last_sample (GstBaseSink *sink);
-
-GST_BASE_API
-void gst_base_sink_set_last_sample_enabled (GstBaseSink *sink, gboolean enabled);
-
-GST_BASE_API
-gboolean gst_base_sink_is_last_sample_enabled (GstBaseSink *sink);
-
-/* latency */
-
-GST_BASE_API
-gboolean gst_base_sink_query_latency (GstBaseSink *sink, gboolean *live, gboolean *upstream_live,
- GstClockTime *min_latency, GstClockTime *max_latency);
-GST_BASE_API
-GstClockTime gst_base_sink_get_latency (GstBaseSink *sink);
-
-/* render delay */
-
-GST_BASE_API
-void gst_base_sink_set_render_delay (GstBaseSink *sink, GstClockTime delay);
-
-GST_BASE_API
-GstClockTime gst_base_sink_get_render_delay (GstBaseSink *sink);
-
-/* blocksize */
-
-GST_BASE_API
-void gst_base_sink_set_blocksize (GstBaseSink *sink, guint blocksize);
-
-GST_BASE_API
-guint gst_base_sink_get_blocksize (GstBaseSink *sink);
-
-/* throttle-time */
-
-GST_BASE_API
-void gst_base_sink_set_throttle_time (GstBaseSink *sink, guint64 throttle);
-
-GST_BASE_API
-guint64 gst_base_sink_get_throttle_time (GstBaseSink *sink);
-
-/* max-bitrate */
-
-GST_BASE_API
-void gst_base_sink_set_max_bitrate (GstBaseSink *sink, guint64 max_bitrate);
-
-GST_BASE_API
-guint64 gst_base_sink_get_max_bitrate (GstBaseSink *sink);
-
-/* processing deadline */
-GST_BASE_API
-void gst_base_sink_set_processing_deadline (GstBaseSink *sink, GstClockTime processing_deadline);
-
-GST_BASE_API
-GstClockTime gst_base_sink_get_processing_deadline (GstBaseSink *sink);
-
-GST_BASE_API
-GstClockReturn gst_base_sink_wait_clock (GstBaseSink *sink, GstClockTime time,
- GstClockTimeDiff * jitter);
-GST_BASE_API
-GstFlowReturn gst_base_sink_wait (GstBaseSink *sink, GstClockTime time,
- GstClockTimeDiff *jitter);
-
-GST_BASE_API
-GstStructure *gst_base_sink_get_stats (GstBaseSink * sink);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSink, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_BASE_SINK_H__ */
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
deleted file mode 100644
index 2ba04cbcb4..0000000000
--- a/libs/gst/base/gstbasesrc.c
+++ /dev/null
@@ -1,4139 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000,2005 Wim Taymans <wim@fluendo.com>
- *
- * gstbasesrc.c:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstbasesrc
- * @title: GstBaseSrc
- * @short_description: Base class for getrange based source elements
- * @see_also: #GstPushSrc, #GstBaseTransform, #GstBaseSink
- *
- * This is a generic base class for source elements. The following
- * types of sources are supported:
- *
- * * random access sources like files
- * * seekable sources
- * * live sources
- *
- * The source can be configured to operate in any #GstFormat with the
- * gst_base_src_set_format() method. The currently set format determines
- * the format of the internal #GstSegment and any %GST_EVENT_SEGMENT
- * events. The default format for #GstBaseSrc is %GST_FORMAT_BYTES.
- *
- * #GstBaseSrc always supports push mode scheduling. If the following
- * conditions are met, it also supports pull mode scheduling:
- *
- * * The format is set to %GST_FORMAT_BYTES (default).
- * * #GstBaseSrcClass::is_seekable returns %TRUE.
- *
- * If all the conditions are met for operating in pull mode, #GstBaseSrc is
- * automatically seekable in push mode as well. The following conditions must
- * be met to make the element seekable in push mode when the format is not
- * %GST_FORMAT_BYTES:
- *
- * * #GstBaseSrcClass::is_seekable returns %TRUE.
- * * #GstBaseSrcClass::query can convert all supported seek formats to the
- * internal format as set with gst_base_src_set_format().
- * * #GstBaseSrcClass::do_seek is implemented, performs the seek and returns
- * %TRUE.
- *
- * When the element does not meet the requirements to operate in pull mode, the
- * offset and length in the #GstBaseSrcClass::create method should be ignored.
- * It is recommended to subclass #GstPushSrc instead, in this situation. If the
- * element can operate in pull mode but only with specific offsets and
- * lengths, it is allowed to generate an error when the wrong values are passed
- * to the #GstBaseSrcClass::create function.
- *
- * #GstBaseSrc has support for live sources. Live sources are sources that when
- * paused discard data, such as audio or video capture devices. A typical live
- * source also produces data at a fixed rate and thus provides a clock to publish
- * this rate.
- * Use gst_base_src_set_live() to activate the live source mode.
- *
- * A live source does not produce data in the PAUSED state. This means that the
- * #GstBaseSrcClass::create method will not be called in PAUSED but only in
- * PLAYING. To signal the pipeline that the element will not produce data, the
- * return value from the READY to PAUSED state will be
- * %GST_STATE_CHANGE_NO_PREROLL.
- *
- * A typical live source will timestamp the buffers it creates with the
- * current running time of the pipeline. This is one reason why a live source
- * can only produce data in the PLAYING state, when the clock is actually
- * distributed and running.
- *
- * Live sources that synchronize and block on the clock (an audio source, for
- * example) can use gst_base_src_wait_playing() when the
- * #GstBaseSrcClass::create function was interrupted by a state change to
- * PAUSED.
- *
- * The #GstBaseSrcClass::get_times method can be used to implement pseudo-live
- * sources. It only makes sense to implement the #GstBaseSrcClass::get_times
- * function if the source is a live source. The #GstBaseSrcClass::get_times
- * function should return timestamps starting from 0, as if it were a non-live
- * source. The base class will make sure that the timestamps are transformed
- * into the current running_time. The base source will then wait for the
- * calculated running_time before pushing out the buffer.
- *
- * For live sources, the base class will by default report a latency of 0.
- * For pseudo live sources, the base class will by default measure the difference
- * between the first buffer timestamp and the start time of get_times and will
- * report this value as the latency.
- * Subclasses should override the query function when this behaviour is not
- * acceptable.
- *
- * There is only support in #GstBaseSrc for exactly one source pad, which
- * should be named "src". A source implementation (subclass of #GstBaseSrc)
- * should install a pad template in its class_init function, like so:
- * |[<!-- language="C" -->
- * static void
- * my_element_class_init (GstMyElementClass *klass)
- * {
- * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- * // srctemplate should be a #GstStaticPadTemplate with direction
- * // %GST_PAD_SRC and name "src"
- * gst_element_class_add_static_pad_template (gstelement_class, &amp;srctemplate);
- *
- * gst_element_class_set_static_metadata (gstelement_class,
- * "Source name",
- * "Source",
- * "My Source element",
- * "The author <my.sink@my.email>");
- * }
- * ]|
- *
- * ## Controlled shutdown of live sources in applications
- *
- * Applications that record from a live source may want to stop recording
- * in a controlled way, so that the recording is stopped, but the data
- * already in the pipeline is processed to the end (remember that many live
- * sources would go on recording forever otherwise). For that to happen the
- * application needs to make the source stop recording and send an EOS
- * event down the pipeline. The application would then wait for an
- * EOS message posted on the pipeline's bus to know when all data has
- * been processed and the pipeline can safely be stopped.
- *
- * An application may send an EOS event to a source element to make it
- * perform the EOS logic (send EOS event downstream or post a
- * %GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
- * with the gst_element_send_event() function on the element or its parent bin.
- *
- * After the EOS has been sent to the element, the application should wait for
- * an EOS message to be posted on the pipeline's bus. Once this EOS message is
- * received, it may safely shut down the entire pipeline.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <gst/gst_private.h>
-#include <gst/glib-compat-private.h>
-
-#include "gstbasesrc.h"
-#include <gst/gst-i18n-lib.h>
-
-GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
-#define GST_CAT_DEFAULT gst_base_src_debug
-
-#define GST_LIVE_GET_LOCK(elem) (&GST_BASE_SRC_CAST(elem)->live_lock)
-#define GST_LIVE_LOCK(elem) g_mutex_lock(GST_LIVE_GET_LOCK(elem))
-#define GST_LIVE_TRYLOCK(elem) g_mutex_trylock(GST_LIVE_GET_LOCK(elem))
-#define GST_LIVE_UNLOCK(elem) g_mutex_unlock(GST_LIVE_GET_LOCK(elem))
-#define GST_LIVE_GET_COND(elem) (&GST_BASE_SRC_CAST(elem)->live_cond)
-#define GST_LIVE_WAIT(elem) g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))
-#define GST_LIVE_WAIT_UNTIL(elem, end_time) g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem), end_time)
-#define GST_LIVE_SIGNAL(elem) g_cond_signal (GST_LIVE_GET_COND (elem));
-#define GST_LIVE_BROADCAST(elem) g_cond_broadcast (GST_LIVE_GET_COND (elem));
-
-
-#define GST_ASYNC_GET_COND(elem) (&GST_BASE_SRC_CAST(elem)->priv->async_cond)
-#define GST_ASYNC_WAIT(elem) g_cond_wait (GST_ASYNC_GET_COND (elem), GST_OBJECT_GET_LOCK (elem))
-#define GST_ASYNC_SIGNAL(elem) g_cond_signal (GST_ASYNC_GET_COND (elem));
-
-#define CLEAR_PENDING_EOS(bsrc) \
- G_STMT_START { \
- g_atomic_int_set (&bsrc->priv->has_pending_eos, FALSE); \
- gst_event_replace (&bsrc->priv->pending_eos, NULL); \
- } G_STMT_END
-
-
-/* BaseSrc signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-#define DEFAULT_BLOCKSIZE 4096
-#define DEFAULT_NUM_BUFFERS -1
-#define DEFAULT_DO_TIMESTAMP FALSE
-
-enum
-{
- PROP_0,
- PROP_BLOCKSIZE,
- PROP_NUM_BUFFERS,
-#ifndef GST_REMOVE_DEPRECATED
- PROP_TYPEFIND,
-#endif
- PROP_DO_TIMESTAMP
-};
-
-/* The basesrc implementation need to respect the following locking order:
- * 1. STREAM_LOCK
- * 2. LIVE_LOCK
- * 3. OBJECT_LOCK
- */
-struct _GstBaseSrcPrivate
-{
- gboolean discont; /* STREAM_LOCK */
- gboolean flushing; /* LIVE_LOCK */
-
- GstFlowReturn start_result; /* OBJECT_LOCK */
- gboolean async; /* OBJECT_LOCK */
-
- /* if a stream-start event should be sent */
- gboolean stream_start_pending; /* STREAM_LOCK */
-
- /* if segment should be sent and a
- * seqnum if it was originated by a seek */
- gboolean segment_pending; /* OBJECT_LOCK */
- guint32 segment_seqnum; /* OBJECT_LOCK */
-
- /* if EOS is pending (atomic) */
- GstEvent *pending_eos; /* OBJECT_LOCK */
- gint has_pending_eos; /* atomic */
-
- /* if the eos was caused by a forced eos from the application */
- gboolean forced_eos; /* LIVE_LOCK */
-
- /* startup latency is the time it takes between going to PLAYING and producing
- * the first BUFFER with running_time 0. This value is included in the latency
- * reporting. */
- GstClockTime latency; /* OBJECT_LOCK */
- /* timestamp offset, this is the offset add to the values of gst_times for
- * pseudo live sources */
- GstClockTimeDiff ts_offset; /* OBJECT_LOCK */
-
- gboolean do_timestamp; /* OBJECT_LOCK */
- gint dynamic_size; /* atomic */
- gint automatic_eos; /* atomic */
-
- /* stream sequence number */
- guint32 seqnum; /* STREAM_LOCK */
-
- /* pending events (TAG, CUSTOM_BOTH, CUSTOM_DOWNSTREAM) to be
- * pushed in the data stream */
- GList *pending_events; /* OBJECT_LOCK */
- gint have_events; /* OBJECT_LOCK */
-
- /* QoS *//* with LOCK */
- gdouble proportion; /* OBJECT_LOCK */
- GstClockTime earliest_time; /* OBJECT_LOCK */
-
- GstBufferPool *pool; /* OBJECT_LOCK */
- GstAllocator *allocator; /* OBJECT_LOCK */
- GstAllocationParams params; /* OBJECT_LOCK */
-
- GCond async_cond; /* OBJECT_LOCK */
-
- /* for _submit_buffer_list() */
- GstBufferList *pending_bufferlist;
-};
-
-#define BASE_SRC_HAS_PENDING_BUFFER_LIST(src) \
- ((src)->priv->pending_bufferlist != NULL)
-
-static GstElementClass *parent_class = NULL;
-static gint private_offset = 0;
-
-static void gst_base_src_class_init (GstBaseSrcClass * klass);
-static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
-static void gst_base_src_finalize (GObject * object);
-
-
-GType
-gst_base_src_get_type (void)
-{
- static gsize base_src_type = 0;
-
- if (g_once_init_enter (&base_src_type)) {
- GType _type;
- static const GTypeInfo base_src_info = {
- sizeof (GstBaseSrcClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_base_src_class_init,
- NULL,
- NULL,
- sizeof (GstBaseSrc),
- 0,
- (GInstanceInitFunc) gst_base_src_init,
- };
-
- _type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
-
- private_offset =
- g_type_add_instance_private (_type, sizeof (GstBaseSrcPrivate));
-
- g_once_init_leave (&base_src_type, _type);
- }
- return base_src_type;
-}
-
-static inline GstBaseSrcPrivate *
-gst_base_src_get_instance_private (GstBaseSrc * self)
-{
- return (G_STRUCT_MEMBER_P (self, private_offset));
-}
-
-static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc,
- GstCaps * filter);
-static GstCaps *gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps);
-static GstCaps *gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps);
-
-static gboolean gst_base_src_is_random_access (GstBaseSrc * src);
-static gboolean gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active);
-static void gst_base_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_base_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_base_src_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);
-static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event);
-
-static gboolean gst_base_src_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-
-static void gst_base_src_set_pool_flushing (GstBaseSrc * basesrc,
- gboolean flushing);
-static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
-static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,
- GstSegment * segment);
-static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);
-static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src,
- GstEvent * event, GstSegment * segment);
-static GstFlowReturn gst_base_src_default_create (GstBaseSrc * basesrc,
- guint64 offset, guint size, GstBuffer ** buf);
-static GstFlowReturn gst_base_src_default_alloc (GstBaseSrc * basesrc,
- guint64 offset, guint size, GstBuffer ** buf);
-static gboolean gst_base_src_decide_allocation_default (GstBaseSrc * basesrc,
- GstQuery * query);
-
-static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc,
- gboolean flushing);
-
-static gboolean gst_base_src_start (GstBaseSrc * basesrc);
-static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
-
-static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
- GstStateChange transition);
-
-static void gst_base_src_loop (GstPad * pad);
-static GstFlowReturn gst_base_src_getrange (GstPad * pad, GstObject * parent,
- guint64 offset, guint length, GstBuffer ** buf);
-static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
- guint length, GstBuffer ** buf);
-static gboolean gst_base_src_seekable (GstBaseSrc * src);
-static gboolean gst_base_src_negotiate_unlocked (GstBaseSrc * basesrc);
-static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset,
- guint * length, gboolean force);
-
-static void
-gst_base_src_class_init (GstBaseSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
- if (private_offset != 0)
- g_type_class_adjust_private_offset (klass, &private_offset);
-
- GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_base_src_finalize;
- gobject_class->set_property = gst_base_src_set_property;
- gobject_class->get_property = gst_base_src_get_property;
-
- g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
- g_param_spec_uint ("blocksize", "Block size",
- "Size in bytes to read per buffer (-1 = default)", 0, G_MAXUINT,
- DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
- g_param_spec_int ("num-buffers", "num-buffers",
- "Number of buffers to output before sending EOS (-1 = unlimited)",
- -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-#ifndef GST_REMOVE_DEPRECATED
- g_object_class_install_property (gobject_class, PROP_TYPEFIND,
- g_param_spec_boolean ("typefind", "Typefind",
- "Run typefind before negotiating (deprecated, non-functional)", FALSE,
- G_PARAM_READWRITE | G_PARAM_DEPRECATED | G_PARAM_STATIC_STRINGS));
-#endif
- g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP,
- g_param_spec_boolean ("do-timestamp", "Do timestamp",
- "Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_base_src_change_state);
- gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);
-
- klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_src_default_get_caps);
- klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate);
- klass->fixate = GST_DEBUG_FUNCPTR (gst_base_src_default_fixate);
- klass->prepare_seek_segment =
- GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment);
- klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);
- klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);
- klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);
- klass->create = GST_DEBUG_FUNCPTR (gst_base_src_default_create);
- klass->alloc = GST_DEBUG_FUNCPTR (gst_base_src_default_alloc);
- klass->decide_allocation =
- GST_DEBUG_FUNCPTR (gst_base_src_decide_allocation_default);
-
- /* Registering debug symbols for function pointers */
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_mode);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getrange);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate);
-}
-
-static void
-gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
-{
- GstPad *pad;
- GstPadTemplate *pad_template;
-
- basesrc->priv = gst_base_src_get_instance_private (basesrc);
-
- basesrc->is_live = FALSE;
- g_mutex_init (&basesrc->live_lock);
- g_cond_init (&basesrc->live_cond);
- basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
- basesrc->num_buffers_left = -1;
- g_atomic_int_set (&basesrc->priv->automatic_eos, TRUE);
-
- basesrc->can_activate_push = TRUE;
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
- g_return_if_fail (pad_template != NULL);
-
- GST_DEBUG_OBJECT (basesrc, "creating src pad");
- pad = gst_pad_new_from_template (pad_template, "src");
-
- GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
- gst_pad_set_activatemode_function (pad, gst_base_src_activate_mode);
- gst_pad_set_event_function (pad, gst_base_src_event);
- gst_pad_set_query_function (pad, gst_base_src_query);
- gst_pad_set_getrange_function (pad, gst_base_src_getrange);
-
- /* hold pointer to pad */
- basesrc->srcpad = pad;
- GST_DEBUG_OBJECT (basesrc, "adding src pad");
- gst_element_add_pad (GST_ELEMENT (basesrc), pad);
-
- basesrc->blocksize = DEFAULT_BLOCKSIZE;
- basesrc->clock_id = NULL;
- /* we operate in BYTES by default */
- gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
- basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
- g_atomic_int_set (&basesrc->priv->have_events, FALSE);
-
- g_cond_init (&basesrc->priv->async_cond);
- basesrc->priv->start_result = GST_FLOW_FLUSHING;
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
- GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_FLAG_SOURCE);
-
- GST_DEBUG_OBJECT (basesrc, "init done");
-}
-
-static void
-gst_base_src_finalize (GObject * object)
-{
- GstBaseSrc *basesrc;
- GstEvent **event_p;
-
- basesrc = GST_BASE_SRC (object);
-
- g_mutex_clear (&basesrc->live_lock);
- g_cond_clear (&basesrc->live_cond);
- g_cond_clear (&basesrc->priv->async_cond);
-
- event_p = &basesrc->pending_seek;
- gst_event_replace (event_p, NULL);
-
- if (basesrc->priv->pending_events) {
- g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref,
- NULL);
- g_list_free (basesrc->priv->pending_events);
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/* Call with LIVE_LOCK held */
-static GstFlowReturn
-gst_base_src_wait_playing_unlocked (GstBaseSrc * src)
-{
- while (G_UNLIKELY (!src->live_running && !src->priv->flushing)) {
- /* block until the state changes, or we get a flush, or something */
- GST_DEBUG_OBJECT (src, "live source waiting for running state");
- GST_LIVE_WAIT (src);
- GST_DEBUG_OBJECT (src, "live source unlocked");
- }
-
- if (src->priv->flushing)
- goto flushing;
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (src, "we are flushing");
- return GST_FLOW_FLUSHING;
- }
-}
-
-
-/**
- * gst_base_src_wait_playing:
- * @src: the src
- *
- * If the #GstBaseSrcClass::create method performs its own synchronisation
- * against the clock it must unblock when going from PLAYING to the PAUSED state
- * and call this method before continuing to produce the remaining data.
- *
- * This function will block until a state change to PLAYING happens (in which
- * case this function returns %GST_FLOW_OK) or the processing must be stopped due
- * to a state change to READY or a FLUSH event (in which case this function
- * returns %GST_FLOW_FLUSHING).
- *
- * Returns: %GST_FLOW_OK if @src is PLAYING and processing can
- * continue. Any other return value should be returned from the create vmethod.
- */
-GstFlowReturn
-gst_base_src_wait_playing (GstBaseSrc * src)
-{
- GstFlowReturn ret;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), GST_FLOW_ERROR);
-
- GST_LIVE_LOCK (src);
- ret = gst_base_src_wait_playing_unlocked (src);
- GST_LIVE_UNLOCK (src);
-
- return ret;
-}
-
-/**
- * gst_base_src_set_live:
- * @src: base source instance
- * @live: new live-mode
- *
- * If the element listens to a live source, @live should
- * be set to %TRUE.
- *
- * A live source will not produce data in the PAUSED state and
- * will therefore not be able to participate in the PREROLL phase
- * of a pipeline. To signal this fact to the application and the
- * pipeline, the state change return value of the live source will
- * be GST_STATE_CHANGE_NO_PREROLL.
- */
-void
-gst_base_src_set_live (GstBaseSrc * src, gboolean live)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- GST_OBJECT_LOCK (src);
- src->is_live = live;
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_is_live:
- * @src: base source instance
- *
- * Check if an element is in live mode.
- *
- * Returns: %TRUE if element is in live mode.
- */
-gboolean
-gst_base_src_is_live (GstBaseSrc * src)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
-
- GST_OBJECT_LOCK (src);
- result = src->is_live;
- GST_OBJECT_UNLOCK (src);
-
- return result;
-}
-
-/**
- * gst_base_src_set_format:
- * @src: base source instance
- * @format: the format to use
- *
- * Sets the default format of the source. This will be the format used
- * for sending SEGMENT events and for performing seeks.
- *
- * If a format of GST_FORMAT_BYTES is set, the element will be able to
- * operate in pull mode if the #GstBaseSrcClass::is_seekable returns %TRUE.
- *
- * This function must only be called in states < %GST_STATE_PAUSED.
- */
-void
-gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
- g_return_if_fail (GST_STATE (src) <= GST_STATE_READY);
-
- GST_OBJECT_LOCK (src);
- gst_segment_init (&src->segment, format);
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_set_dynamic_size:
- * @src: base source instance
- * @dynamic: new dynamic size mode
- *
- * If not @dynamic, size is only updated when needed, such as when trying to
- * read past current tracked size. Otherwise, size is checked for upon each
- * read.
- */
-void
-gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- g_atomic_int_set (&src->priv->dynamic_size, dynamic);
-}
-
-/**
- * gst_base_src_set_automatic_eos:
- * @src: base source instance
- * @automatic_eos: automatic eos
- *
- * If @automatic_eos is %TRUE, @src will automatically go EOS if a buffer
- * after the total size is returned. By default this is %TRUE but sources
- * that can't return an authoritative size and only know that they're EOS
- * when trying to read more should set this to %FALSE.
- *
- * When @src operates in %GST_FORMAT_TIME, #GstBaseSrc will send an EOS
- * when a buffer outside of the currently configured segment is pushed if
- * @automatic_eos is %TRUE. Since 1.16, if @automatic_eos is %FALSE an
- * EOS will be pushed only when the #GstBaseSrcClass::create implementation
- * returns %GST_FLOW_EOS.
- *
- * Since: 1.4
- */
-void
-gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- g_atomic_int_set (&src->priv->automatic_eos, automatic_eos);
-}
-
-/**
- * gst_base_src_set_async:
- * @src: base source instance
- * @async: new async mode
- *
- * Configure async behaviour in @src, no state change will block. The open,
- * close, start, stop, play and pause virtual methods will be executed in a
- * different thread and are thus allowed to perform blocking operations. Any
- * blocking operation should be unblocked with the unlock vmethod.
- */
-void
-gst_base_src_set_async (GstBaseSrc * src, gboolean async)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- GST_OBJECT_LOCK (src);
- src->priv->async = async;
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_is_async:
- * @src: base source instance
- *
- * Get the current async behaviour of @src. See also gst_base_src_set_async().
- *
- * Returns: %TRUE if @src is operating in async mode.
- */
-gboolean
-gst_base_src_is_async (GstBaseSrc * src)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
-
- GST_OBJECT_LOCK (src);
- res = src->priv->async;
- GST_OBJECT_UNLOCK (src);
-
- return res;
-}
-
-
-/**
- * gst_base_src_query_latency:
- * @src: the source
- * @live: (out) (allow-none): if the source is live
- * @min_latency: (out) (allow-none): the min latency of the source
- * @max_latency: (out) (allow-none): the max latency of the source
- *
- * Query the source for the latency parameters. @live will be %TRUE when @src is
- * configured as a live source. @min_latency and @max_latency will be set
- * to the difference between the running time and the timestamp of the first
- * buffer.
- *
- * This function is mostly used by subclasses.
- *
- * Returns: %TRUE if the query succeeded.
- */
-gboolean
-gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
- GstClockTime * min_latency, GstClockTime * max_latency)
-{
- GstClockTime min;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
-
- GST_OBJECT_LOCK (src);
- if (live)
- *live = src->is_live;
-
- /* if we have a startup latency, report this one, else report 0. Subclasses
- * are supposed to override the query function if they want something
- * else. */
- if (src->priv->latency != -1)
- min = src->priv->latency;
- else
- min = 0;
-
- if (min_latency)
- *min_latency = min;
- if (max_latency)
- *max_latency = min;
-
- GST_LOG_OBJECT (src, "latency: live %d, min %" GST_TIME_FORMAT
- ", max %" GST_TIME_FORMAT, src->is_live, GST_TIME_ARGS (min),
- GST_TIME_ARGS (min));
- GST_OBJECT_UNLOCK (src);
-
- return TRUE;
-}
-
-/**
- * gst_base_src_set_blocksize:
- * @src: the source
- * @blocksize: the new blocksize in bytes
- *
- * Set the number of bytes that @src will push out with each buffer. When
- * @blocksize is set to -1, a default length will be used.
- */
-void
-gst_base_src_set_blocksize (GstBaseSrc * src, guint blocksize)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- GST_OBJECT_LOCK (src);
- src->blocksize = blocksize;
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_get_blocksize:
- * @src: the source
- *
- * Get the number of bytes that @src will push out with each buffer.
- *
- * Returns: the number of bytes pushed with each buffer.
- */
-guint
-gst_base_src_get_blocksize (GstBaseSrc * src)
-{
- gint res;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), 0);
-
- GST_OBJECT_LOCK (src);
- res = src->blocksize;
- GST_OBJECT_UNLOCK (src);
-
- return res;
-}
-
-
-/**
- * gst_base_src_set_do_timestamp:
- * @src: the source
- * @timestamp: enable or disable timestamping
- *
- * Configure @src to automatically timestamp outgoing buffers based on the
- * current running_time of the pipeline. This property is mostly useful for live
- * sources.
- */
-void
-gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- GST_OBJECT_LOCK (src);
- src->priv->do_timestamp = timestamp;
- if (timestamp && src->segment.format != GST_FORMAT_TIME)
- gst_segment_init (&src->segment, GST_FORMAT_TIME);
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_get_do_timestamp:
- * @src: the source
- *
- * Query if @src timestamps outgoing buffers based on the current running_time.
- *
- * Returns: %TRUE if the base class will automatically timestamp outgoing buffers.
- */
-gboolean
-gst_base_src_get_do_timestamp (GstBaseSrc * src)
-{
- gboolean res;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
-
- GST_OBJECT_LOCK (src);
- res = src->priv->do_timestamp;
- GST_OBJECT_UNLOCK (src);
-
- return res;
-}
-
-/**
- * gst_base_src_new_seamless_segment:
- * @src: The source
- * @start: The new start value for the segment
- * @stop: Stop value for the new segment
- * @time: The new time value for the start of the new segment
- *
- * Prepare a new seamless segment for emission downstream. This function must
- * only be called by derived sub-classes, and only from the #GstBaseSrcClass::create function,
- * as the stream-lock needs to be held.
- *
- * The format for the new segment will be the current format of the source, as
- * configured with gst_base_src_set_format()
- *
- * Returns: %TRUE if preparation of the seamless segment succeeded.
- *
- * Deprecated: 1.18: Use gst_base_src_new_segment()
- */
-gboolean
-gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
- gint64 time)
-{
- gboolean res = TRUE;
-
- GST_OBJECT_LOCK (src);
-
- src->segment.base = gst_segment_to_running_time (&src->segment,
- src->segment.format, src->segment.position);
- src->segment.position = src->segment.start = start;
- src->segment.stop = stop;
- src->segment.time = time;
-
- /* Mark pending segment. Will be sent before next data */
- src->priv->segment_pending = TRUE;
- src->priv->segment_seqnum = gst_util_seqnum_next ();
-
- GST_DEBUG_OBJECT (src,
- "Starting new seamless segment. Start %" GST_TIME_FORMAT " stop %"
- GST_TIME_FORMAT " time %" GST_TIME_FORMAT " base %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
- GST_TIME_ARGS (src->segment.base));
-
- GST_OBJECT_UNLOCK (src);
-
- src->priv->discont = TRUE;
- src->running = TRUE;
-
- return res;
-}
-
-/**
- * gst_base_src_new_segment:
- * @src: a #GstBaseSrc
- * @segment: a pointer to a #GstSegment
- *
- * Prepare a new segment for emission downstream. This function must
- * only be called by derived sub-classes, and only from the #GstBaseSrcClass::create function,
- * as the stream-lock needs to be held.
- *
- * The format for the @segment must be identical with the current format
- * of the source, as configured with gst_base_src_set_format().
- *
- * The format of @src must not be %GST_FORMAT_UNDEFINED and the format
- * should be configured via gst_base_src_set_format() before calling this method.
- *
- * Returns: %TRUE if preparation of new segment succeeded.
- *
- * Since: 1.18
- */
-gboolean
-gst_base_src_new_segment (GstBaseSrc * src, const GstSegment * segment)
-{
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
- g_return_val_if_fail (segment != NULL, FALSE);
-
- GST_OBJECT_LOCK (src);
-
- if (src->segment.format == GST_FORMAT_UNDEFINED) {
- /* subclass must set valid format before calling this method */
- GST_WARNING_OBJECT (src, "segment format is not configured yet, ignore");
- GST_OBJECT_UNLOCK (src);
- return FALSE;
- }
-
- if (src->segment.format != segment->format) {
- GST_WARNING_OBJECT (src, "segment format mismatched, ignore");
- GST_OBJECT_UNLOCK (src);
- return FALSE;
- }
-
- gst_segment_copy_into (segment, &src->segment);
-
- /* Mark pending segment. Will be sent before next data */
- src->priv->segment_pending = TRUE;
- src->priv->segment_seqnum = gst_util_seqnum_next ();
-
- GST_DEBUG_OBJECT (src, "Starting new segment %" GST_SEGMENT_FORMAT, segment);
-
- GST_OBJECT_UNLOCK (src);
-
- src->running = TRUE;
-
- return TRUE;
-}
-
-/* called with STREAM_LOCK */
-static gboolean
-gst_base_src_send_stream_start (GstBaseSrc * src)
-{
- gboolean ret = TRUE;
-
- if (src->priv->stream_start_pending) {
- gchar *stream_id;
- GstEvent *event;
-
- stream_id =
- gst_pad_create_stream_id (src->srcpad, GST_ELEMENT_CAST (src), NULL);
-
- GST_DEBUG_OBJECT (src, "Pushing STREAM_START");
- event = gst_event_new_stream_start (stream_id);
- gst_event_set_group_id (event, gst_util_group_id_next ());
-
- ret = gst_pad_push_event (src->srcpad, event);
- src->priv->stream_start_pending = FALSE;
- g_free (stream_id);
- }
-
- return ret;
-}
-
-/**
- * gst_base_src_set_caps:
- * @src: a #GstBaseSrc
- * @caps: (transfer none): a #GstCaps
- *
- * Set new caps on the basesrc source pad.
- *
- * Returns: %TRUE if the caps could be set
- */
-gboolean
-gst_base_src_set_caps (GstBaseSrc * src, GstCaps * caps)
-{
- GstBaseSrcClass *bclass;
- gboolean res = TRUE;
- GstCaps *current_caps;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- gst_base_src_send_stream_start (src);
-
- current_caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (src));
- if (current_caps && gst_caps_is_equal (current_caps, caps)) {
- GST_DEBUG_OBJECT (src, "New caps equal to old ones: %" GST_PTR_FORMAT,
- caps);
- res = TRUE;
- } else {
- if (bclass->set_caps)
- res = bclass->set_caps (src, caps);
-
- if (res)
- res = gst_pad_push_event (src->srcpad, gst_event_new_caps (caps));
- }
-
- if (current_caps)
- gst_caps_unref (current_caps);
-
- return res;
-}
-
-static GstCaps *
-gst_base_src_default_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
-{
- GstCaps *caps = NULL;
- GstPadTemplate *pad_template;
- GstBaseSrcClass *bclass;
-
- bclass = GST_BASE_SRC_GET_CLASS (bsrc);
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
-
- if (pad_template != NULL) {
- caps = gst_pad_template_get_caps (pad_template);
-
- if (filter) {
- GstCaps *intersection;
-
- intersection =
- gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (caps);
- caps = intersection;
- }
- }
- return caps;
-}
-
-static GstCaps *
-gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps)
-{
- GST_DEBUG_OBJECT (bsrc, "using default caps fixate function");
- return gst_caps_fixate (caps);
-}
-
-static GstCaps *
-gst_base_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
-{
- GstBaseSrcClass *bclass;
-
- bclass = GST_BASE_SRC_GET_CLASS (bsrc);
-
- if (bclass->fixate)
- caps = bclass->fixate (bsrc, caps);
-
- return caps;
-}
-
-static gboolean
-gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
-{
- gboolean res;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- GstFormat format;
-
- gst_query_parse_position (query, &format, NULL);
-
- GST_DEBUG_OBJECT (src, "position query in format %s",
- gst_format_get_name (format));
-
- switch (format) {
- case GST_FORMAT_PERCENT:
- {
- gint64 percent;
- gint64 position;
- gint64 duration;
-
- GST_OBJECT_LOCK (src);
- position = src->segment.position;
- duration = src->segment.duration;
- GST_OBJECT_UNLOCK (src);
-
- if (position != -1 && duration != -1) {
- if (position < duration)
- percent = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, position,
- duration);
- else
- percent = GST_FORMAT_PERCENT_MAX;
- } else
- percent = -1;
-
- gst_query_set_position (query, GST_FORMAT_PERCENT, percent);
- res = TRUE;
- break;
- }
- default:
- {
- gint64 position;
- GstFormat seg_format;
-
- GST_OBJECT_LOCK (src);
- position =
- gst_segment_to_stream_time (&src->segment, src->segment.format,
- src->segment.position);
- seg_format = src->segment.format;
- GST_OBJECT_UNLOCK (src);
-
- if (position != -1) {
- /* convert to requested format */
- res =
- gst_pad_query_convert (src->srcpad, seg_format,
- position, format, &position);
- } else
- res = TRUE;
-
- if (res)
- gst_query_set_position (query, format, position);
-
- break;
- }
- }
- break;
- }
- case GST_QUERY_DURATION:
- {
- GstFormat format;
-
- gst_query_parse_duration (query, &format, NULL);
-
- GST_DEBUG_OBJECT (src, "duration query in format %s",
- gst_format_get_name (format));
-
- switch (format) {
- case GST_FORMAT_PERCENT:
- gst_query_set_duration (query, GST_FORMAT_PERCENT,
- GST_FORMAT_PERCENT_MAX);
- res = TRUE;
- break;
- default:
- {
- gint64 duration;
- GstFormat seg_format;
- guint length = 0;
-
- /* may have to refresh duration */
- gst_base_src_update_length (src, 0, &length,
- g_atomic_int_get (&src->priv->dynamic_size));
-
- /* this is the duration as configured by the subclass. */
- GST_OBJECT_LOCK (src);
- duration = src->segment.duration;
- seg_format = src->segment.format;
- GST_OBJECT_UNLOCK (src);
-
- GST_LOG_OBJECT (src, "duration %" G_GINT64_FORMAT ", format %s",
- duration, gst_format_get_name (seg_format));
-
- if (duration != -1) {
- /* convert to requested format, if this fails, we have a duration
- * but we cannot answer the query, we must return FALSE. */
- res =
- gst_pad_query_convert (src->srcpad, seg_format,
- duration, format, &duration);
- } else {
- /* The subclass did not configure a duration, we assume that the
- * media has an unknown duration then and we return TRUE to report
- * this. Note that this is not the same as returning FALSE, which
- * means that we cannot report the duration at all. */
- res = TRUE;
- }
-
- if (res)
- gst_query_set_duration (query, format, duration);
-
- break;
- }
- }
- break;
- }
-
- case GST_QUERY_SEEKING:
- {
- GstFormat format, seg_format;
- gint64 duration;
-
- GST_OBJECT_LOCK (src);
- duration = src->segment.duration;
- seg_format = src->segment.format;
- GST_OBJECT_UNLOCK (src);
-
- gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
- if (format == seg_format) {
- gst_query_set_seeking (query, seg_format,
- gst_base_src_seekable (src), 0, duration);
- res = TRUE;
- } else {
- /* FIXME 2.0: return TRUE + seekable=FALSE for SEEKING query here */
- /* Don't reply to the query to make up for demuxers which don't
- * handle the SEEKING query yet. Players like Totem will fall back
- * to the duration when the SEEKING query isn't answered. */
- res = FALSE;
- }
- break;
- }
- case GST_QUERY_SEGMENT:
- {
- GstFormat format;
- gint64 start, stop;
-
- GST_OBJECT_LOCK (src);
-
- format = src->segment.format;
-
- start =
- gst_segment_to_stream_time (&src->segment, format,
- src->segment.start);
- if ((stop = src->segment.stop) == -1)
- stop = src->segment.duration;
- else
- stop = gst_segment_to_stream_time (&src->segment, format, stop);
-
- gst_query_set_segment (query, src->segment.rate, format, start, stop);
-
- GST_OBJECT_UNLOCK (src);
- res = TRUE;
- break;
- }
-
- case GST_QUERY_FORMATS:
- {
- gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
- GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
- res = TRUE;
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-
- /* we can only convert between equal formats... */
- if (src_fmt == dest_fmt) {
- dest_val = src_val;
- res = TRUE;
- } else
- res = FALSE;
-
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- case GST_QUERY_LATENCY:
- {
- GstClockTime min, max;
- gboolean live;
-
- /* Subclasses should override and implement something useful */
- res = gst_base_src_query_latency (src, &live, &min, &max);
-
- GST_LOG_OBJECT (src, "report latency: live %d, min %" GST_TIME_FORMAT
- ", max %" GST_TIME_FORMAT, live, GST_TIME_ARGS (min),
- GST_TIME_ARGS (max));
-
- gst_query_set_latency (query, live, min, max);
- break;
- }
- case GST_QUERY_JITTER:
- case GST_QUERY_RATE:
- res = FALSE;
- break;
- case GST_QUERY_BUFFERING:
- {
- GstFormat format, seg_format;
- gint64 start, stop, estimated;
-
- gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL);
-
- GST_DEBUG_OBJECT (src, "buffering query in format %s",
- gst_format_get_name (format));
-
- GST_OBJECT_LOCK (src);
- if (src->random_access) {
- estimated = 0;
- start = 0;
- if (format == GST_FORMAT_PERCENT)
- stop = GST_FORMAT_PERCENT_MAX;
- else
- stop = src->segment.duration;
- } else {
- estimated = -1;
- start = -1;
- stop = -1;
- }
- seg_format = src->segment.format;
- GST_OBJECT_UNLOCK (src);
-
- /* convert to required format. When the conversion fails, we can't answer
- * the query. When the value is unknown, we can don't perform conversion
- * but report TRUE. */
- if (format != GST_FORMAT_PERCENT && stop != -1) {
- res = gst_pad_query_convert (src->srcpad, seg_format,
- stop, format, &stop);
- } else {
- res = TRUE;
- }
- if (res && format != GST_FORMAT_PERCENT && start != -1)
- res = gst_pad_query_convert (src->srcpad, seg_format,
- start, format, &start);
-
- gst_query_set_buffering_range (query, format, start, stop, estimated);
- break;
- }
- case GST_QUERY_SCHEDULING:
- {
- gboolean random_access;
-
- random_access = gst_base_src_is_random_access (src);
-
- /* we can operate in getrange mode if the native format is bytes
- * and we are seekable, this condition is set in the random_access
- * flag and is set in the _start() method. */
- gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
- if (random_access)
- gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
- gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
-
- res = TRUE;
- break;
- }
- case GST_QUERY_CAPS:
- {
- GstBaseSrcClass *bclass;
- GstCaps *caps, *filter;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
- if (bclass->get_caps) {
- gst_query_parse_caps (query, &filter);
- if ((caps = bclass->get_caps (src, filter))) {
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- res = TRUE;
- } else {
- res = FALSE;
- }
- } else
- res = FALSE;
- break;
- }
- case GST_QUERY_URI:{
- if (GST_IS_URI_HANDLER (src)) {
- gchar *uri = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
-
- if (uri != NULL) {
- gst_query_set_uri (query, uri);
- g_free (uri);
- res = TRUE;
- } else {
- res = FALSE;
- }
- } else {
- res = FALSE;
- }
- break;
- }
- default:
- res = FALSE;
- break;
- }
- GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),
- res);
-
- return res;
-}
-
-static gboolean
-gst_base_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstBaseSrc *src;
- GstBaseSrcClass *bclass;
- gboolean result = FALSE;
-
- src = GST_BASE_SRC (parent);
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- if (bclass->query)
- result = bclass->query (src, query);
-
- return result;
-}
-
-static gboolean
-gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment)
-{
- gboolean res = TRUE;
-
- /* update our offset if the start/stop position was updated */
- if (segment->format == GST_FORMAT_BYTES) {
- segment->time = segment->start;
- } else if (segment->start == 0) {
- /* seek to start, we can implement a default for this. */
- segment->time = 0;
- } else {
- res = FALSE;
- GST_INFO_OBJECT (src, "Can't do a default seek");
- }
-
- return res;
-}
-
-static gboolean
-gst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment)
-{
- GstBaseSrcClass *bclass;
- gboolean result = FALSE;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- GST_INFO_OBJECT (src, "seeking: %" GST_SEGMENT_FORMAT, segment);
-
- if (bclass->do_seek)
- result = bclass->do_seek (src, segment);
-
- return result;
-}
-
-#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))
-
-static gboolean
-gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
- GstSegment * segment)
-{
- /* By default, we try one of 2 things:
- * - For absolute seek positions, convert the requested position to our
- * configured processing format and place it in the output segment \
- * - For relative seek positions, convert our current (input) values to the
- * seek format, adjust by the relative seek offset and then convert back to
- * the processing format
- */
- GstSeekType start_type, stop_type;
- gint64 start, stop;
- GstSeekFlags flags;
- GstFormat seek_format, dest_format;
- gdouble rate;
- gboolean update;
- gboolean res = TRUE;
-
- gst_event_parse_seek (event, &rate, &seek_format, &flags,
- &start_type, &start, &stop_type, &stop);
- dest_format = segment->format;
-
- if (seek_format == dest_format) {
- gst_segment_do_seek (segment, rate, seek_format, flags,
- start_type, start, stop_type, stop, &update);
- return TRUE;
- }
-
- if (start_type != GST_SEEK_TYPE_NONE) {
- /* FIXME: Handle seek_end by converting the input segment vals */
- res =
- gst_pad_query_convert (src->srcpad, seek_format, start, dest_format,
- &start);
- start_type = GST_SEEK_TYPE_SET;
- }
-
- if (res && stop_type != GST_SEEK_TYPE_NONE) {
- /* FIXME: Handle seek_end by converting the input segment vals */
- res =
- gst_pad_query_convert (src->srcpad, seek_format, stop, dest_format,
- &stop);
- stop_type = GST_SEEK_TYPE_SET;
- }
-
- /* And finally, configure our output segment in the desired format */
- if (res) {
- res =
- gst_segment_do_seek (segment, rate, dest_format, flags, start_type,
- start, stop_type, stop, &update);
- }
-
- if (!res)
- goto no_format;
-
- return res;
-
-no_format:
- {
- GST_DEBUG_OBJECT (src, "undefined format given, seek aborted.");
- return FALSE;
- }
-}
-
-static gboolean
-gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
- GstSegment * seeksegment)
-{
- GstBaseSrcClass *bclass;
- gboolean result = FALSE;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- if (bclass->prepare_seek_segment)
- result = bclass->prepare_seek_segment (src, event, seeksegment);
-
- return result;
-}
-
-static GstFlowReturn
-gst_base_src_default_alloc (GstBaseSrc * src, guint64 offset,
- guint size, GstBuffer ** buffer)
-{
- GstFlowReturn ret;
- GstBaseSrcPrivate *priv = src->priv;
- GstBufferPool *pool = NULL;
- GstAllocator *allocator = NULL;
- GstAllocationParams params;
-
- GST_OBJECT_LOCK (src);
- if (priv->pool) {
- pool = gst_object_ref (priv->pool);
- } else if (priv->allocator) {
- allocator = gst_object_ref (priv->allocator);
- }
- params = priv->params;
- GST_OBJECT_UNLOCK (src);
-
- if (pool) {
- ret = gst_buffer_pool_acquire_buffer (pool, buffer, NULL);
- } else if (size != -1) {
- *buffer = gst_buffer_new_allocate (allocator, size, &params);
- if (G_UNLIKELY (*buffer == NULL))
- goto alloc_failed;
-
- ret = GST_FLOW_OK;
- } else {
- GST_WARNING_OBJECT (src, "Not trying to alloc %u bytes. Blocksize not set?",
- size);
- goto alloc_failed;
- }
-
-done:
- if (pool)
- gst_object_unref (pool);
- if (allocator)
- gst_object_unref (allocator);
-
- return ret;
-
- /* ERRORS */
-alloc_failed:
- {
- GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
- ret = GST_FLOW_ERROR;
- goto done;
- }
-}
-
-static GstFlowReturn
-gst_base_src_default_create (GstBaseSrc * src, guint64 offset,
- guint size, GstBuffer ** buffer)
-{
- GstBaseSrcClass *bclass;
- GstFlowReturn ret;
- GstBuffer *res_buf;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- if (G_UNLIKELY (!bclass->alloc))
- goto no_function;
- if (G_UNLIKELY (!bclass->fill))
- goto no_function;
-
- if (*buffer == NULL) {
- /* downstream did not provide us with a buffer to fill, allocate one
- * ourselves */
- ret = bclass->alloc (src, offset, size, &res_buf);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto alloc_failed;
- } else {
- res_buf = *buffer;
- }
-
- if (G_LIKELY (size > 0)) {
- /* only call fill when there is a size */
- ret = bclass->fill (src, offset, size, res_buf);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto not_ok;
- }
-
- *buffer = res_buf;
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-no_function:
- {
- GST_DEBUG_OBJECT (src, "no fill or alloc function");
- return GST_FLOW_NOT_SUPPORTED;
- }
-alloc_failed:
- {
- GST_DEBUG_OBJECT (src, "Failed to allocate buffer of %u bytes", size);
- return ret;
- }
-not_ok:
- {
- GST_DEBUG_OBJECT (src, "fill returned %d (%s)", ret,
- gst_flow_get_name (ret));
- if (*buffer == NULL)
- gst_buffer_unref (res_buf);
- return ret;
- }
-}
-
-/* this code implements the seeking. It is a good example
- * handling all cases.
- *
- * A seek updates the currently configured segment.start
- * and segment.stop values based on the SEEK_TYPE. If the
- * segment.start value is updated, a seek to this new position
- * should be performed.
- *
- * The seek can only be executed when we are not currently
- * streaming any data, to make sure that this is the case, we
- * acquire the STREAM_LOCK which is taken when we are in the
- * _loop() function or when a getrange() is called. Normally
- * we will not receive a seek if we are operating in pull mode
- * though. When we operate as a live source we might block on the live
- * cond, which does not release the STREAM_LOCK. Therefore we will try
- * to grab the LIVE_LOCK instead of the STREAM_LOCK to make sure it is
- * safe to perform the seek.
- *
- * When we are in the loop() function, we might be in the middle
- * of pushing a buffer, which might block in a sink. To make sure
- * that the push gets unblocked we push out a FLUSH_START event.
- * Our loop function will get a FLUSHING return value from
- * the push and will pause, effectively releasing the STREAM_LOCK.
- *
- * For a non-flushing seek, we pause the task, which might eventually
- * release the STREAM_LOCK. We say eventually because when the sink
- * blocks on the sample we might wait a very long time until the sink
- * unblocks the sample. In any case we acquire the STREAM_LOCK and
- * can continue the seek. A non-flushing seek is normally done in a
- * running pipeline to perform seamless playback, this means that the sink is
- * PLAYING and will return from its chain function.
- * In the case of a non-flushing seek we need to make sure that the
- * data we output after the seek is continuous with the previous data,
- * this is because a non-flushing seek does not reset the running-time
- * to 0. We do this by closing the currently running segment, ie. sending
- * a new_segment event with the stop position set to the last processed
- * position.
- *
- * After updating the segment.start/stop values, we prepare for
- * streaming again. We push out a FLUSH_STOP to make the peer pad
- * accept data again and we start our task again.
- *
- * A segment seek posts a message on the bus saying that the playback
- * of the segment started. We store the segment flag internally because
- * when we reach the segment.stop we have to post a segment.done
- * instead of EOS when doing a segment seek.
- */
-static gboolean
-gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
-{
- gboolean res = TRUE, tres;
- gdouble rate;
- GstFormat seek_format, dest_format;
- GstSeekFlags flags;
- GstSeekType start_type, stop_type;
- gint64 start, stop;
- gboolean flush;
- gboolean update;
- gboolean relative_seek = FALSE;
- gboolean seekseg_configured = FALSE;
- GstSegment seeksegment;
- guint32 seqnum;
- GstEvent *tevent;
-
- GST_DEBUG_OBJECT (src, "doing seek: %" GST_PTR_FORMAT, event);
-
- GST_OBJECT_LOCK (src);
- dest_format = src->segment.format;
- GST_OBJECT_UNLOCK (src);
-
- if (event) {
- gst_event_parse_seek (event, &rate, &seek_format, &flags,
- &start_type, &start, &stop_type, &stop);
-
- relative_seek = SEEK_TYPE_IS_RELATIVE (start_type) ||
- SEEK_TYPE_IS_RELATIVE (stop_type);
-
- if (dest_format != seek_format && !relative_seek) {
- /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it
- * here before taking the stream lock, otherwise we must convert it later,
- * once we have the stream lock and can read the last configures segment
- * start and stop positions */
- gst_segment_init (&seeksegment, dest_format);
-
- if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment))
- goto prepare_failed;
-
- seekseg_configured = TRUE;
- }
-
- flush = flags & GST_SEEK_FLAG_FLUSH;
- seqnum = gst_event_get_seqnum (event);
- } else {
- flush = FALSE;
- /* get next seqnum */
- seqnum = gst_util_seqnum_next ();
- }
-
- /* send flush start */
- if (flush) {
- tevent = gst_event_new_flush_start ();
- gst_event_set_seqnum (tevent, seqnum);
- gst_pad_push_event (src->srcpad, tevent);
- } else
- gst_pad_pause_task (src->srcpad);
-
- /* unblock streaming thread. */
- if (unlock)
- gst_base_src_set_flushing (src, TRUE);
-
- /* grab streaming lock, this should eventually be possible, either
- * because the task is paused, our streaming thread stopped
- * or because our peer is flushing. */
- GST_PAD_STREAM_LOCK (src->srcpad);
- if (G_UNLIKELY (src->priv->seqnum == seqnum)) {
- /* we have seen this event before, issue a warning for now */
- GST_WARNING_OBJECT (src, "duplicate event found %" G_GUINT32_FORMAT,
- seqnum);
- } else {
- src->priv->seqnum = seqnum;
- GST_DEBUG_OBJECT (src, "seek with seqnum %" G_GUINT32_FORMAT, seqnum);
- }
-
- if (unlock)
- gst_base_src_set_flushing (src, FALSE);
-
- /* If we configured the seeksegment above, don't overwrite it now. Otherwise
- * copy the current segment info into the temp segment that we can actually
- * attempt the seek with. We only update the real segment if the seek succeeds. */
- if (!seekseg_configured) {
- memcpy (&seeksegment, &src->segment, sizeof (GstSegment));
-
- /* now configure the final seek segment */
- if (event) {
- if (seeksegment.format != seek_format) {
- /* OK, here's where we give the subclass a chance to convert the relative
- * seek into an absolute one in the processing format. We set up any
- * absolute seek above, before taking the stream lock. */
- if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) {
- GST_DEBUG_OBJECT (src, "Preparing the seek failed after flushing. "
- "Aborting seek");
- res = FALSE;
- }
- } else {
- /* The seek format matches our processing format, no need to ask the
- * the subclass to configure the segment. */
- gst_segment_do_seek (&seeksegment, rate, seek_format, flags,
- start_type, start, stop_type, stop, &update);
- }
- }
- /* Else, no seek event passed, so we're just (re)starting the
- current segment. */
- }
-
- if (res) {
- GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
- seeksegment.start, seeksegment.stop, seeksegment.position);
-
- /* do the seek, segment.position contains the new position. */
- res = gst_base_src_do_seek (src, &seeksegment);
- }
-
- /* and prepare to continue streaming */
- if (flush) {
- tevent = gst_event_new_flush_stop (TRUE);
- gst_event_set_seqnum (tevent, seqnum);
- /* send flush stop, peer will accept data and events again. We
- * are not yet providing data as we still have the STREAM_LOCK. */
- gst_pad_push_event (src->srcpad, tevent);
- }
-
- /* The subclass must have converted the segment to the processing format
- * by now */
- if (res && seeksegment.format != dest_format) {
- GST_DEBUG_OBJECT (src, "Subclass failed to prepare a seek segment "
- "in the correct format. Aborting seek.");
- res = FALSE;
- }
-
- /* if the seek was successful, we update our real segment and push
- * out the new segment. */
- if (res) {
- GST_OBJECT_LOCK (src);
- memcpy (&src->segment, &seeksegment, sizeof (GstSegment));
- GST_OBJECT_UNLOCK (src);
-
- if (seeksegment.flags & GST_SEGMENT_FLAG_SEGMENT) {
- GstMessage *message;
-
- message = gst_message_new_segment_start (GST_OBJECT (src),
- seeksegment.format, seeksegment.position);
- gst_message_set_seqnum (message, seqnum);
-
- gst_element_post_message (GST_ELEMENT (src), message);
- }
-
- src->priv->segment_pending = TRUE;
- src->priv->segment_seqnum = seqnum;
- }
-
- src->priv->discont = TRUE;
- src->running = TRUE;
- /* and restart the task in case it got paused explicitly or by
- * the FLUSH_START event we pushed out. */
- tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
- src->srcpad, NULL);
- if (res && !tres)
- res = FALSE;
-
- /* and release the lock again so we can continue streaming */
- GST_PAD_STREAM_UNLOCK (src->srcpad);
-
- return res;
-
- /* ERROR */
-prepare_failed:
- GST_DEBUG_OBJECT (src, "Preparing the seek failed before flushing. "
- "Aborting seek");
- return FALSE;
-}
-
-/* all events send to this element directly. This is mainly done from the
- * application.
- */
-static gboolean
-gst_base_src_send_event (GstElement * element, GstEvent * event)
-{
- GstBaseSrc *src;
- gboolean result = FALSE;
- GstBaseSrcClass *bclass;
-
- src = GST_BASE_SRC (element);
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- GST_DEBUG_OBJECT (src, "handling event %p %" GST_PTR_FORMAT, event, event);
-
- switch (GST_EVENT_TYPE (event)) {
- /* bidirectional events */
- case GST_EVENT_FLUSH_START:
- GST_DEBUG_OBJECT (src, "pushing flush-start event downstream");
-
- result = gst_pad_push_event (src->srcpad, event);
- gst_base_src_set_flushing (src, TRUE);
- event = NULL;
- break;
- case GST_EVENT_FLUSH_STOP:
- {
- gboolean start;
-
- GST_PAD_STREAM_LOCK (src->srcpad);
- gst_base_src_set_flushing (src, FALSE);
-
- GST_DEBUG_OBJECT (src, "pushing flush-stop event downstream");
- result = gst_pad_push_event (src->srcpad, event);
-
- /* For external flush, restart the task .. */
- GST_LIVE_LOCK (src);
- src->priv->segment_pending = TRUE;
-
- GST_OBJECT_LOCK (src->srcpad);
- start = (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH);
- GST_OBJECT_UNLOCK (src->srcpad);
-
- /* ... and for live sources, only if in playing state */
- if (src->is_live) {
- if (!src->live_running)
- start = FALSE;
- }
-
- if (start)
- gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
- src->srcpad, NULL);
-
- GST_LIVE_UNLOCK (src);
- GST_PAD_STREAM_UNLOCK (src->srcpad);
-
- event = NULL;
- break;
- }
-
- /* downstream serialized events */
- case GST_EVENT_EOS:
- {
- gboolean push_mode;
-
- /* queue EOS and make sure the task or pull function performs the EOS
- * actions.
- *
- * For push mode, This will be done in 3 steps. It is required to not
- * block here as gst_element_send_event() will hold the STATE_LOCK, hence
- * blocking would prevent asynchronous state change to complete.
- *
- * 1. We stop the streaming thread
- * 2. We set the pending eos
- * 3. We start the streaming thread again, so it is performed
- * asynchronously.
- *
- * For pull mode, we simply mark the pending EOS without flushing.
- */
-
- GST_OBJECT_LOCK (src->srcpad);
- push_mode = GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH;
- GST_OBJECT_UNLOCK (src->srcpad);
-
- if (push_mode) {
- gst_base_src_set_flushing (src, TRUE);
-
- GST_PAD_STREAM_LOCK (src->srcpad);
- gst_base_src_set_flushing (src, FALSE);
-
- GST_OBJECT_LOCK (src);
- g_atomic_int_set (&src->priv->has_pending_eos, TRUE);
- if (src->priv->pending_eos)
- gst_event_unref (src->priv->pending_eos);
- src->priv->pending_eos = event;
- GST_OBJECT_UNLOCK (src);
-
- GST_DEBUG_OBJECT (src,
- "EOS marked, start task for asynchronous handling");
- gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
- src->srcpad, NULL);
-
- GST_PAD_STREAM_UNLOCK (src->srcpad);
- } else {
- /* In pull mode, we need not to return flushing to downstream, though
- * the stream lock is not kept after getrange was unblocked */
- GST_OBJECT_LOCK (src);
- g_atomic_int_set (&src->priv->has_pending_eos, TRUE);
- if (src->priv->pending_eos)
- gst_event_unref (src->priv->pending_eos);
- src->priv->pending_eos = event;
- GST_OBJECT_UNLOCK (src);
-
- gst_base_src_set_pool_flushing (src, TRUE);
- if (bclass->unlock)
- bclass->unlock (src);
-
- GST_PAD_STREAM_LOCK (src->srcpad);
- if (bclass->unlock_stop)
- bclass->unlock_stop (src);
- gst_base_src_set_pool_flushing (src, TRUE);
- GST_PAD_STREAM_UNLOCK (src->srcpad);
- }
-
-
- event = NULL;
- result = TRUE;
- break;
- }
- case GST_EVENT_SEGMENT:
- /* sending random SEGMENT downstream can break sync. */
- break;
- case GST_EVENT_TAG:
- case GST_EVENT_SINK_MESSAGE:
- case GST_EVENT_CUSTOM_DOWNSTREAM:
- case GST_EVENT_CUSTOM_BOTH:
- case GST_EVENT_PROTECTION:
- /* Insert TAG, CUSTOM_DOWNSTREAM, CUSTOM_BOTH, PROTECTION in the dataflow */
- GST_OBJECT_LOCK (src);
- src->priv->pending_events =
- g_list_append (src->priv->pending_events, event);
- g_atomic_int_set (&src->priv->have_events, TRUE);
- GST_OBJECT_UNLOCK (src);
- event = NULL;
- result = TRUE;
- break;
- case GST_EVENT_BUFFERSIZE:
- /* does not seem to make much sense currently */
- break;
-
- /* upstream events */
- case GST_EVENT_QOS:
- /* elements should override send_event and do something */
- break;
- case GST_EVENT_SEEK:
- {
- gboolean started;
-
- GST_OBJECT_LOCK (src->srcpad);
- if (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PULL)
- goto wrong_mode;
- started = GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH;
- GST_OBJECT_UNLOCK (src->srcpad);
-
- if (started) {
- GST_DEBUG_OBJECT (src, "performing seek");
- /* when we are running in push mode, we can execute the
- * seek right now. */
- result = gst_base_src_perform_seek (src, event, TRUE);
- } else {
- GstEvent **event_p;
-
- /* else we store the event and execute the seek when we
- * get activated */
- GST_OBJECT_LOCK (src);
- GST_DEBUG_OBJECT (src, "queueing seek");
- event_p = &src->pending_seek;
- gst_event_replace ((GstEvent **) event_p, event);
- GST_OBJECT_UNLOCK (src);
- /* assume the seek will work */
- result = TRUE;
- }
- break;
- }
- case GST_EVENT_NAVIGATION:
- /* could make sense for elements that do something with navigation events
- * but then they would need to override the send_event function */
- break;
- case GST_EVENT_LATENCY:
- /* does not seem to make sense currently */
- break;
-
- /* custom events */
- case GST_EVENT_CUSTOM_UPSTREAM:
- /* override send_event if you want this */
- break;
- case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
- case GST_EVENT_CUSTOM_BOTH_OOB:
- /* insert a random custom event into the pipeline */
- GST_DEBUG_OBJECT (src, "pushing custom OOB event downstream");
- result = gst_pad_push_event (src->srcpad, event);
- /* we gave away the ref to the event in the push */
- event = NULL;
- break;
- default:
- break;
- }
-done:
- /* if we still have a ref to the event, unref it now */
- if (event)
- gst_event_unref (event);
-
- return result;
-
- /* ERRORS */
-wrong_mode:
- {
- GST_DEBUG_OBJECT (src, "cannot perform seek when operating in pull mode");
- GST_OBJECT_UNLOCK (src->srcpad);
- result = FALSE;
- goto done;
- }
-}
-
-static gboolean
-gst_base_src_seekable (GstBaseSrc * src)
-{
- GstBaseSrcClass *bclass;
- bclass = GST_BASE_SRC_GET_CLASS (src);
- if (bclass->is_seekable)
- return bclass->is_seekable (src);
- else
- return FALSE;
-}
-
-static void
-gst_base_src_update_qos (GstBaseSrc * src,
- gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
-{
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, src,
- "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
- GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
-
- GST_OBJECT_LOCK (src);
- src->priv->proportion = proportion;
- src->priv->earliest_time = timestamp + diff;
- GST_OBJECT_UNLOCK (src);
-}
-
-
-static gboolean
-gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
-{
- gboolean result;
-
- GST_DEBUG_OBJECT (src, "handle event %" GST_PTR_FORMAT, event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- /* is normally called when in push mode */
- if (!gst_base_src_seekable (src))
- goto not_seekable;
-
- result = gst_base_src_perform_seek (src, event, TRUE);
- break;
- case GST_EVENT_FLUSH_START:
- /* cancel any blocking getrange, is normally called
- * when in pull mode. */
- result = gst_base_src_set_flushing (src, TRUE);
- break;
- case GST_EVENT_FLUSH_STOP:
- result = gst_base_src_set_flushing (src, FALSE);
- break;
- case GST_EVENT_QOS:
- {
- gdouble proportion;
- GstClockTimeDiff diff;
- GstClockTime timestamp;
-
- gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
- gst_base_src_update_qos (src, proportion, diff, timestamp);
- result = TRUE;
- break;
- }
- case GST_EVENT_RECONFIGURE:
- result = TRUE;
- break;
- case GST_EVENT_LATENCY:
- result = TRUE;
- break;
- default:
- result = FALSE;
- break;
- }
- return result;
-
- /* ERRORS */
-not_seekable:
- {
- GST_DEBUG_OBJECT (src, "is not seekable");
- return FALSE;
- }
-}
-
-static gboolean
-gst_base_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstBaseSrc *src;
- GstBaseSrcClass *bclass;
- gboolean result = FALSE;
-
- src = GST_BASE_SRC (parent);
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- if (bclass->event) {
- if (!(result = bclass->event (src, event)))
- goto subclass_failed;
- }
-
-done:
- gst_event_unref (event);
-
- return result;
-
- /* ERRORS */
-subclass_failed:
- {
- GST_DEBUG_OBJECT (src, "subclass refused event");
- goto done;
- }
-}
-
-static void
-gst_base_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstBaseSrc *src;
-
- src = GST_BASE_SRC (object);
-
- switch (prop_id) {
- case PROP_BLOCKSIZE:
- gst_base_src_set_blocksize (src, g_value_get_uint (value));
- break;
- case PROP_NUM_BUFFERS:
- src->num_buffers = g_value_get_int (value);
- break;
-#ifndef GST_REMOVE_DEPRECATED
- case PROP_TYPEFIND:
- src->typefind = g_value_get_boolean (value);
- break;
-#endif
- case PROP_DO_TIMESTAMP:
- gst_base_src_set_do_timestamp (src, g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstBaseSrc *src;
-
- src = GST_BASE_SRC (object);
-
- switch (prop_id) {
- case PROP_BLOCKSIZE:
- g_value_set_uint (value, gst_base_src_get_blocksize (src));
- break;
- case PROP_NUM_BUFFERS:
- g_value_set_int (value, src->num_buffers);
- break;
-#ifndef GST_REMOVE_DEPRECATED
- case PROP_TYPEFIND:
- g_value_set_boolean (value, src->typefind);
- break;
-#endif
- case PROP_DO_TIMESTAMP:
- g_value_set_boolean (value, gst_base_src_get_do_timestamp (src));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* with STREAM_LOCK and LOCK */
-static GstClockReturn
-gst_base_src_wait (GstBaseSrc * basesrc, GstClock * clock, GstClockTime time)
-{
- GstClockReturn ret;
- GstClockID id;
-
- id = gst_clock_new_single_shot_id (clock, time);
-
- basesrc->clock_id = id;
- /* release the live lock while waiting */
- GST_LIVE_UNLOCK (basesrc);
-
- ret = gst_clock_id_wait (id, NULL);
-
- GST_LIVE_LOCK (basesrc);
- gst_clock_id_unref (id);
- basesrc->clock_id = NULL;
-
- return ret;
-}
-
-/* perform synchronisation on a buffer.
- * with STREAM_LOCK.
- */
-static GstClockReturn
-gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
-{
- GstClockReturn result;
- GstClockTime start, end;
- GstBaseSrcClass *bclass;
- GstClockTime base_time;
- GstClock *clock;
- GstClockTime now = GST_CLOCK_TIME_NONE, pts, dts, timestamp;
- gboolean do_timestamp, first, pseudo_live, is_live;
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
-
- start = end = -1;
- if (bclass->get_times)
- bclass->get_times (basesrc, buffer, &start, &end);
-
- /* get buffer timestamp */
- dts = GST_BUFFER_DTS (buffer);
- pts = GST_BUFFER_PTS (buffer);
-
- if (GST_CLOCK_TIME_IS_VALID (dts))
- timestamp = dts;
- else
- timestamp = pts;
-
- /* grab the lock to prepare for clocking and calculate the startup
- * latency. */
- GST_OBJECT_LOCK (basesrc);
-
- is_live = basesrc->is_live;
- /* if we are asked to sync against the clock we are a pseudo live element */
- pseudo_live = (start != -1 && is_live);
- /* check for the first buffer */
- first = (basesrc->priv->latency == -1);
-
- if (timestamp != -1 && pseudo_live) {
- GstClockTime latency;
-
- /* we have a timestamp and a sync time, latency is the diff */
- if (timestamp <= start)
- latency = start - timestamp;
- else
- latency = 0;
-
- if (first) {
- GST_DEBUG_OBJECT (basesrc, "pseudo_live with latency %" GST_TIME_FORMAT,
- GST_TIME_ARGS (latency));
- /* first time we calculate latency, just configure */
- basesrc->priv->latency = latency;
- } else {
- if (basesrc->priv->latency != latency) {
- /* we have a new latency, FIXME post latency message */
- basesrc->priv->latency = latency;
- GST_DEBUG_OBJECT (basesrc, "latency changed to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (latency));
- }
- }
- } else if (first) {
- GST_DEBUG_OBJECT (basesrc, "no latency needed, live %d, sync %d",
- is_live, start != -1);
- basesrc->priv->latency = 0;
- }
-
- /* get clock, if no clock, we can't sync or do timestamps */
- if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
- goto no_clock;
- else
- gst_object_ref (clock);
-
- base_time = GST_ELEMENT_CAST (basesrc)->base_time;
-
- do_timestamp = basesrc->priv->do_timestamp;
- GST_OBJECT_UNLOCK (basesrc);
-
- /* first buffer, calculate the timestamp offset */
- if (first) {
- GstClockTime running_time;
-
- now = gst_clock_get_time (clock);
- running_time = now - base_time;
-
- GST_LOG_OBJECT (basesrc,
- "startup PTS: %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT
- ", running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (pts),
- GST_TIME_ARGS (dts), GST_TIME_ARGS (running_time));
-
- if (pseudo_live && timestamp != -1) {
- /* live source and we need to sync, add startup latency to all timestamps
- * to get the real running_time. Live sources should always timestamp
- * according to the current running time. */
- basesrc->priv->ts_offset = GST_CLOCK_DIFF (timestamp, running_time);
-
- GST_LOG_OBJECT (basesrc, "live with sync, ts_offset %" GST_TIME_FORMAT,
- GST_TIME_ARGS (basesrc->priv->ts_offset));
- } else {
- basesrc->priv->ts_offset = 0;
- GST_LOG_OBJECT (basesrc, "no timestamp offset needed");
- }
-
- if (!GST_CLOCK_TIME_IS_VALID (dts)) {
- if (do_timestamp) {
- dts = running_time;
- } else if (!GST_CLOCK_TIME_IS_VALID (pts)) {
- if (GST_CLOCK_TIME_IS_VALID (basesrc->segment.start)) {
- dts = basesrc->segment.start;
- } else {
- dts = 0;
- }
- }
- GST_BUFFER_DTS (buffer) = dts;
-
- GST_LOG_OBJECT (basesrc, "created DTS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (dts));
- }
- } else {
- /* not the first buffer, the timestamp is the diff between the clock and
- * base_time */
- if (do_timestamp && !GST_CLOCK_TIME_IS_VALID (dts)) {
- now = gst_clock_get_time (clock);
-
- dts = now - base_time;
- GST_BUFFER_DTS (buffer) = dts;
-
- GST_LOG_OBJECT (basesrc, "created DTS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (dts));
- }
- }
- if (!GST_CLOCK_TIME_IS_VALID (pts)) {
- if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
- pts = dts;
-
- GST_BUFFER_PTS (buffer) = dts;
-
- GST_LOG_OBJECT (basesrc, "created PTS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (pts));
- }
-
- /* if we don't have a buffer timestamp, we don't sync */
- if (!GST_CLOCK_TIME_IS_VALID (start))
- goto no_sync;
-
- if (is_live) {
- /* for pseudo live sources, add our ts_offset to the timestamp */
- if (GST_CLOCK_TIME_IS_VALID (pts))
- GST_BUFFER_PTS (buffer) += basesrc->priv->ts_offset;
- if (GST_CLOCK_TIME_IS_VALID (dts))
- GST_BUFFER_DTS (buffer) += basesrc->priv->ts_offset;
- start += basesrc->priv->ts_offset;
- }
-
- GST_LOG_OBJECT (basesrc,
- "waiting for clock, base time %" GST_TIME_FORMAT
- ", stream_start %" GST_TIME_FORMAT,
- GST_TIME_ARGS (base_time), GST_TIME_ARGS (start));
-
- result = gst_base_src_wait (basesrc, clock, start + base_time);
-
- gst_object_unref (clock);
-
- GST_LOG_OBJECT (basesrc, "clock entry done: %d", result);
-
- return result;
-
- /* special cases */
-no_clock:
- {
- GST_DEBUG_OBJECT (basesrc, "we have no clock");
- GST_OBJECT_UNLOCK (basesrc);
- return GST_CLOCK_OK;
- }
-no_sync:
- {
- GST_DEBUG_OBJECT (basesrc, "no sync needed");
- gst_object_unref (clock);
- return GST_CLOCK_OK;
- }
-}
-
-/* Called with STREAM_LOCK and LIVE_LOCK */
-static gboolean
-gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length,
- gboolean force)
-{
- guint64 size, maxsize;
- GstBaseSrcClass *bclass;
- gint64 stop;
-
- /* only operate if we are working with bytes */
- if (src->segment.format != GST_FORMAT_BYTES)
- return TRUE;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
- stop = src->segment.stop;
- /* get total file size */
- size = src->segment.duration;
-
- /* when not doing automatic EOS, just use the stop position. We don't use
- * the size to check for EOS */
- if (!g_atomic_int_get (&src->priv->automatic_eos))
- maxsize = stop;
- /* Otherwise, the max amount of bytes to read is the total
- * size or up to the segment.stop if present. */
- else if (stop != -1)
- maxsize = size != -1 ? MIN (size, stop) : stop;
- else
- maxsize = size;
-
- GST_DEBUG_OBJECT (src,
- "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
- ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
- *length, size, stop, maxsize);
-
- /* check size if we have one */
- if (maxsize != -1) {
- /* if we run past the end, check if the file became bigger and
- * retry. Mind wrap when checking. */
- if (G_UNLIKELY (offset >= maxsize || offset + *length >= maxsize || force)) {
- /* see if length of the file changed */
- if (bclass->get_size)
- if (!bclass->get_size (src, &size))
- size = -1;
-
- /* when not doing automatic EOS, just use the stop position. We don't use
- * the size to check for EOS */
- if (!g_atomic_int_get (&src->priv->automatic_eos))
- maxsize = stop;
- /* Otherwise, the max amount of bytes to read is the total
- * size or up to the segment.stop if present. */
- else if (stop != -1)
- maxsize = size != -1 ? MIN (size, stop) : stop;
- else
- maxsize = size;
-
- if (maxsize != -1) {
- /* if we are at or past the end, EOS */
- if (G_UNLIKELY (offset >= maxsize))
- goto unexpected_length;
-
- /* else we can clip to the end */
- if (G_UNLIKELY (offset + *length >= maxsize))
- *length = maxsize - offset;
- }
- }
- }
-
- /* keep track of current duration. segment is in bytes, we checked
- * that above. */
- GST_OBJECT_LOCK (src);
- src->segment.duration = size;
- GST_OBJECT_UNLOCK (src);
-
- return TRUE;
-
- /* ERRORS */
-unexpected_length:
- {
- GST_DEBUG_OBJECT (src, "processing at or past EOS");
- return FALSE;
- }
-}
-
-/* must be called with LIVE_LOCK */
-static GstFlowReturn
-gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
- GstBuffer ** buf)
-{
- GstFlowReturn ret;
- GstBaseSrcClass *bclass;
- GstClockReturn status;
- GstBuffer *res_buf;
- GstBuffer *in_buf;
- gboolean own_res_buf;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
-again:
- if (src->is_live) {
- if (G_UNLIKELY (!src->live_running)) {
- ret = gst_base_src_wait_playing_unlocked (src);
- if (ret != GST_FLOW_OK)
- goto stopped;
- }
- }
-
- if (G_UNLIKELY (!GST_BASE_SRC_IS_STARTED (src)
- && !GST_BASE_SRC_IS_STARTING (src)))
- goto not_started;
-
- if (G_UNLIKELY (!bclass->create))
- goto no_function;
-
- if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length, FALSE)))
- goto unexpected_length;
-
- /* track position */
- GST_OBJECT_LOCK (src);
- if (src->segment.format == GST_FORMAT_BYTES)
- src->segment.position = offset;
- GST_OBJECT_UNLOCK (src);
-
- /* normally we don't count buffers */
- if (G_UNLIKELY (src->num_buffers_left >= 0)) {
- if (src->num_buffers_left == 0)
- goto reached_num_buffers;
- else
- src->num_buffers_left--;
- }
-
- /* don't enter the create function if a pending EOS event was set. For the
- * logic of the has_pending_eos, check the event function of this class. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
- src->priv->forced_eos = TRUE;
- goto eos;
- }
-
- GST_DEBUG_OBJECT (src,
- "calling create offset %" G_GUINT64_FORMAT " length %u, time %"
- G_GINT64_FORMAT, offset, length, src->segment.time);
-
- res_buf = in_buf = *buf;
- own_res_buf = (*buf == NULL);
-
- GST_LIVE_UNLOCK (src);
- ret = bclass->create (src, offset, length, &res_buf);
- GST_LIVE_LOCK (src);
-
- /* As we released the LIVE_LOCK, the state may have changed */
- if (src->is_live) {
- if (G_UNLIKELY (!src->live_running)) {
- GstFlowReturn wait_ret;
- wait_ret = gst_base_src_wait_playing_unlocked (src);
- if (wait_ret != GST_FLOW_OK) {
- if (ret == GST_FLOW_OK && own_res_buf)
- gst_buffer_unref (res_buf);
- ret = wait_ret;
- goto stopped;
- }
- }
- }
-
- /* The create function could be unlocked because we have a pending EOS. It's
- * possible that we have a valid buffer from create that we need to
- * discard when the create function returned _OK. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
- if (ret == GST_FLOW_OK) {
- if (own_res_buf)
- gst_buffer_unref (res_buf);
- }
- src->priv->forced_eos = TRUE;
- goto eos;
- }
-
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto not_ok;
-
- /* fallback in case the create function didn't fill a provided buffer */
- if (in_buf != NULL && res_buf != in_buf) {
- GstMapInfo info;
- gsize copied_size;
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, src, "create function didn't "
- "fill the provided buffer, copying");
-
- if (!gst_buffer_map (in_buf, &info, GST_MAP_WRITE))
- goto map_failed;
-
- copied_size = gst_buffer_extract (res_buf, 0, info.data, info.size);
- gst_buffer_unmap (in_buf, &info);
- gst_buffer_set_size (in_buf, copied_size);
-
- gst_buffer_copy_into (in_buf, res_buf, GST_BUFFER_COPY_METADATA, 0, -1);
-
- gst_buffer_unref (res_buf);
- res_buf = in_buf;
- }
-
- if (res_buf == NULL) {
- GstBufferList *pending_list = src->priv->pending_bufferlist;
-
- if (pending_list == NULL || gst_buffer_list_length (pending_list) == 0)
- goto null_buffer;
-
- res_buf = gst_buffer_list_get_writable (pending_list, 0);
- own_res_buf = FALSE;
- }
-
- /* no timestamp set and we are at offset 0, we can timestamp with 0 */
- if (offset == 0 && src->segment.time == 0
- && GST_BUFFER_DTS (res_buf) == -1 && !src->is_live) {
- GST_DEBUG_OBJECT (src, "setting first timestamp to 0");
- res_buf = gst_buffer_make_writable (res_buf);
- GST_BUFFER_DTS (res_buf) = 0;
- }
-
- /* now sync before pushing the buffer */
- status = gst_base_src_do_sync (src, res_buf);
-
- /* waiting for the clock could have made us flushing */
- if (G_UNLIKELY (src->priv->flushing))
- goto flushing;
-
- switch (status) {
- case GST_CLOCK_EARLY:
- /* the buffer is too late. We currently don't drop the buffer. */
- GST_DEBUG_OBJECT (src, "buffer too late!, returning anyway");
- break;
- case GST_CLOCK_OK:
- /* buffer synchronised properly */
- GST_DEBUG_OBJECT (src, "buffer ok");
- break;
- case GST_CLOCK_UNSCHEDULED:
- /* this case is triggered when we were waiting for the clock and
- * it got unlocked because we did a state change. In any case, get rid of
- * the buffer. */
- if (own_res_buf)
- gst_buffer_unref (res_buf);
-
- if (!src->live_running) {
- /* We return FLUSHING when we are not running to stop the dataflow also
- * get rid of the produced buffer. */
- GST_DEBUG_OBJECT (src,
- "clock was unscheduled (%d), returning FLUSHING", status);
- ret = GST_FLOW_FLUSHING;
- } else {
- /* If we are running when this happens, we quickly switched between
- * pause and playing. We try to produce a new buffer */
- GST_DEBUG_OBJECT (src,
- "clock was unscheduled (%d), but we are running", status);
- goto again;
- }
- break;
- default:
- /* all other result values are unexpected and errors */
- GST_ELEMENT_ERROR (src, CORE, CLOCK,
- (_("Internal clock error.")),
- ("clock returned unexpected return value %d", status));
- if (own_res_buf)
- gst_buffer_unref (res_buf);
- ret = GST_FLOW_ERROR;
- break;
- }
- if (G_LIKELY (ret == GST_FLOW_OK))
- *buf = res_buf;
-
- return ret;
-
- /* ERROR */
-stopped:
- {
- GST_DEBUG_OBJECT (src, "wait_playing returned %d (%s)", ret,
- gst_flow_get_name (ret));
- return ret;
- }
-not_ok:
- {
- GST_DEBUG_OBJECT (src, "create returned %d (%s)", ret,
- gst_flow_get_name (ret));
- return ret;
- }
-map_failed:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, BUSY,
- (_("Failed to map buffer.")),
- ("failed to map result buffer in WRITE mode"));
- if (own_res_buf)
- gst_buffer_unref (res_buf);
- return GST_FLOW_ERROR;
- }
-not_started:
- {
- GST_DEBUG_OBJECT (src, "getrange but not started");
- return GST_FLOW_FLUSHING;
- }
-no_function:
- {
- GST_DEBUG_OBJECT (src, "no create function");
- return GST_FLOW_NOT_SUPPORTED;
- }
-unexpected_length:
- {
- GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT
- ", size=%" G_GINT64_FORMAT ")", length, offset, src->segment.duration);
- return GST_FLOW_EOS;
- }
-reached_num_buffers:
- {
- GST_DEBUG_OBJECT (src, "sent all buffers");
- return GST_FLOW_EOS;
- }
-flushing:
- {
- GST_DEBUG_OBJECT (src, "we are flushing");
- if (own_res_buf)
- gst_buffer_unref (res_buf);
- return GST_FLOW_FLUSHING;
- }
-eos:
- {
- GST_DEBUG_OBJECT (src, "we are EOS");
- return GST_FLOW_EOS;
- }
-null_buffer:
- {
- GST_ELEMENT_ERROR (src, STREAM, FAILED,
- (_("Internal data flow error.")),
- ("Subclass %s neither returned a buffer nor submitted a buffer list "
- "from its create function", G_OBJECT_TYPE_NAME (src)));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_base_src_getrange (GstPad * pad, GstObject * parent, guint64 offset,
- guint length, GstBuffer ** buf)
-{
- GstBaseSrc *src;
- GstFlowReturn res;
-
- src = GST_BASE_SRC_CAST (parent);
-
- GST_LIVE_LOCK (src);
- if (G_UNLIKELY (src->priv->flushing))
- goto flushing;
-
- res = gst_base_src_get_range (src, offset, length, buf);
-
-done:
- GST_LIVE_UNLOCK (src);
-
- return res;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (src, "we are flushing");
- res = GST_FLOW_FLUSHING;
- goto done;
- }
-}
-
-static gboolean
-gst_base_src_is_random_access (GstBaseSrc * src)
-{
- /* we need to start the basesrc to check random access */
- if (!GST_BASE_SRC_IS_STARTED (src)) {
- GST_LOG_OBJECT (src, "doing start/stop to check get_range support");
- if (G_LIKELY (gst_base_src_start (src))) {
- if (gst_base_src_start_wait (src) != GST_FLOW_OK)
- goto start_failed;
- gst_base_src_stop (src);
- }
- }
-
- return src->random_access;
-
- /* ERRORS */
-start_failed:
- {
- GST_DEBUG_OBJECT (src, "failed to start");
- return FALSE;
- }
-}
-
-/* Called with STREAM_LOCK */
-static void
-gst_base_src_loop (GstPad * pad)
-{
- GstBaseSrc *src;
- GstBuffer *buf = NULL;
- GstFlowReturn ret;
- gint64 position;
- gboolean eos;
- guint blocksize;
- GList *pending_events = NULL, *tmp;
-
- eos = FALSE;
-
- src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
-
- /* Just leave immediately if we're flushing */
- GST_LIVE_LOCK (src);
- if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
- goto flushing;
- GST_LIVE_UNLOCK (src);
-
- /* Just return if EOS is pushed again, as the app might be unaware that an
- * EOS have been sent already */
- if (GST_PAD_IS_EOS (pad)) {
- GST_DEBUG_OBJECT (src, "Pad is marked as EOS, pause the task");
- gst_pad_pause_task (pad);
- goto done;
- }
-
- gst_base_src_send_stream_start (src);
-
- /* The stream-start event could've caused something to flush us */
- GST_LIVE_LOCK (src);
- if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
- goto flushing;
- GST_LIVE_UNLOCK (src);
-
- /* check if we need to renegotiate */
- if (gst_pad_check_reconfigure (pad)) {
- if (!gst_base_src_negotiate_unlocked (src)) {
- gst_pad_mark_reconfigure (pad);
- if (GST_PAD_IS_FLUSHING (pad)) {
- GST_LIVE_LOCK (src);
- goto flushing;
- } else {
- goto negotiate_failed;
- }
- }
- }
-
- GST_LIVE_LOCK (src);
-
- if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
- goto flushing;
-
- blocksize = src->blocksize;
-
- /* if we operate in bytes, we can calculate an offset */
- if (src->segment.format == GST_FORMAT_BYTES) {
- position = src->segment.position;
- /* for negative rates, start with subtracting the blocksize */
- if (src->segment.rate < 0.0) {
- /* we cannot go below segment.start */
- if (position > src->segment.start + blocksize)
- position -= blocksize;
- else {
- /* last block, remainder up to segment.start */
- blocksize = position - src->segment.start;
- position = src->segment.start;
- }
- }
- } else
- position = -1;
-
- GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %u",
- GST_TIME_ARGS (position), blocksize);
-
- /* clean up just in case we got interrupted or so last time round */
- if (src->priv->pending_bufferlist != NULL) {
- gst_buffer_list_unref (src->priv->pending_bufferlist);
- src->priv->pending_bufferlist = NULL;
- }
-
- ret = gst_base_src_get_range (src, position, blocksize, &buf);
- if (G_UNLIKELY (ret != GST_FLOW_OK)) {
- GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s",
- gst_flow_get_name (ret));
- GST_LIVE_UNLOCK (src);
- goto pause;
- }
-
- /* Note: at this point buf might be a single buf returned which we own or
- * the first buf of a pending buffer list submitted via submit_buffer_list(),
- * in which case the buffer is owned by the pending buffer list and not us. */
- g_assert (buf != NULL);
-
- /* push events to close/start our segment before we push the buffer. */
- if (G_UNLIKELY (src->priv->segment_pending)) {
- GstEvent *seg_event = gst_event_new_segment (&src->segment);
-
- gst_event_set_seqnum (seg_event, src->priv->segment_seqnum);
- src->priv->segment_seqnum = gst_util_seqnum_next ();
- gst_pad_push_event (pad, seg_event);
- src->priv->segment_pending = FALSE;
- }
-
- if (g_atomic_int_get (&src->priv->have_events)) {
- GST_OBJECT_LOCK (src);
- /* take the events */
- pending_events = src->priv->pending_events;
- src->priv->pending_events = NULL;
- g_atomic_int_set (&src->priv->have_events, FALSE);
- GST_OBJECT_UNLOCK (src);
- }
-
- /* Push out pending events if any */
- if (G_UNLIKELY (pending_events != NULL)) {
- for (tmp = pending_events; tmp; tmp = g_list_next (tmp)) {
- GstEvent *ev = (GstEvent *) tmp->data;
- gst_pad_push_event (pad, ev);
- }
- g_list_free (pending_events);
- }
-
- /* figure out the new position */
- switch (src->segment.format) {
- case GST_FORMAT_BYTES:
- {
- guint bufsize = gst_buffer_get_size (buf);
-
- /* we subtracted above for negative rates */
- if (src->segment.rate >= 0.0)
- position += bufsize;
- break;
- }
- case GST_FORMAT_TIME:
- {
- GstClockTime start, duration;
-
- start = GST_BUFFER_TIMESTAMP (buf);
- duration = GST_BUFFER_DURATION (buf);
-
- if (GST_CLOCK_TIME_IS_VALID (start))
- position = start;
- else
- position = src->segment.position;
-
- if (GST_CLOCK_TIME_IS_VALID (duration)) {
- if (src->segment.rate >= 0.0)
- position += duration;
- }
- break;
- }
- case GST_FORMAT_DEFAULT:
- if (src->segment.rate >= 0.0)
- position = GST_BUFFER_OFFSET_END (buf);
- else
- position = GST_BUFFER_OFFSET (buf);
- break;
- default:
- position = -1;
- break;
- }
- if (position != -1) {
- if (src->segment.rate >= 0.0) {
- /* positive rate, check if we reached the stop */
- if (src->segment.stop != -1) {
- if (position >= src->segment.stop) {
- if (g_atomic_int_get (&src->priv->automatic_eos))
- eos = TRUE;
- position = src->segment.stop;
- }
- }
- } else {
- /* negative rate, check if we reached the start. start is always set to
- * something different from -1 */
- if (position <= src->segment.start) {
- if (g_atomic_int_get (&src->priv->automatic_eos))
- eos = TRUE;
- position = src->segment.start;
- }
- /* when going reverse, all buffers are DISCONT */
- src->priv->discont = TRUE;
- }
- GST_OBJECT_LOCK (src);
- src->segment.position = position;
- GST_OBJECT_UNLOCK (src);
- }
-
- if (G_UNLIKELY (src->priv->discont)) {
- GST_INFO_OBJECT (src, "marking pending DISCONT");
- buf = gst_buffer_make_writable (buf);
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- src->priv->discont = FALSE;
- }
- GST_LIVE_UNLOCK (src);
-
- /* push buffer or buffer list */
- if (src->priv->pending_bufferlist != NULL) {
- ret = gst_pad_push_list (pad, src->priv->pending_bufferlist);
- src->priv->pending_bufferlist = NULL;
- } else {
- ret = gst_pad_push (pad, buf);
- }
-
- if (G_UNLIKELY (ret != GST_FLOW_OK)) {
- if (ret == GST_FLOW_NOT_NEGOTIATED) {
- goto not_negotiated;
- }
- GST_INFO_OBJECT (src, "pausing after gst_pad_push() = %s",
- gst_flow_get_name (ret));
- goto pause;
- }
-
- /* Segment pending means that a new segment was configured
- * during this loop run */
- if (G_UNLIKELY (eos && !src->priv->segment_pending)) {
- GST_INFO_OBJECT (src, "pausing after end of segment");
- ret = GST_FLOW_EOS;
- goto pause;
- }
-
-done:
- return;
-
- /* special cases */
-not_negotiated:
- {
- if (gst_pad_needs_reconfigure (pad)) {
- GST_DEBUG_OBJECT (src, "Retrying to renegotiate");
- return;
- }
- /* fallthrough when push returns NOT_NEGOTIATED and we don't have
- * a pending negotiation request on our srcpad */
- }
-negotiate_failed:
- {
- GST_DEBUG_OBJECT (src, "Not negotiated");
- ret = GST_FLOW_NOT_NEGOTIATED;
- goto pause;
- }
-flushing:
- {
- GST_DEBUG_OBJECT (src, "we are flushing");
- GST_LIVE_UNLOCK (src);
- ret = GST_FLOW_FLUSHING;
- goto pause;
- }
-pause:
- {
- GstEvent *event;
-
- GST_DEBUG_OBJECT (src, "pausing task, reason %s", gst_flow_get_name (ret));
- src->running = FALSE;
- gst_pad_pause_task (pad);
- if (ret == GST_FLOW_EOS) {
- gboolean flag_segment;
- GstFormat format;
- gint64 position;
-
- flag_segment = (src->segment.flags & GST_SEGMENT_FLAG_SEGMENT) != 0;
- format = src->segment.format;
- position = src->segment.position;
-
- /* perform EOS logic */
- if (src->priv->forced_eos) {
- g_assert (g_atomic_int_get (&src->priv->has_pending_eos));
- GST_OBJECT_LOCK (src);
- event = src->priv->pending_eos;
- src->priv->pending_eos = NULL;
- GST_OBJECT_UNLOCK (src);
-
- } else if (flag_segment) {
- GstMessage *message;
-
- message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
- format, position);
- gst_message_set_seqnum (message, src->priv->seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (src), message);
- event = gst_event_new_segment_done (format, position);
- gst_event_set_seqnum (event, src->priv->seqnum);
-
- } else {
- event = gst_event_new_eos ();
- gst_event_set_seqnum (event, src->priv->seqnum);
- }
-
- gst_pad_push_event (pad, event);
- src->priv->forced_eos = FALSE;
-
- } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_EOS) {
- event = gst_event_new_eos ();
- gst_event_set_seqnum (event, src->priv->seqnum);
- /* for fatal errors we post an error message, post the error
- * first so the app knows about the error first.
- * Also don't do this for FLUSHING because it happens
- * due to flushing and posting an error message because of
- * that is the wrong thing to do, e.g. when we're doing
- * a flushing seek. */
- GST_ELEMENT_FLOW_ERROR (src, ret);
- gst_pad_push_event (pad, event);
- }
- goto done;
- }
-}
-
-static gboolean
-gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
- GstAllocator * allocator, const GstAllocationParams * params)
-{
- GstAllocator *oldalloc;
- GstBufferPool *oldpool;
- GstBaseSrcPrivate *priv = basesrc->priv;
-
- if (pool) {
- GST_DEBUG_OBJECT (basesrc, "activate pool");
- if (!gst_buffer_pool_set_active (pool, TRUE))
- goto activate_failed;
- }
-
- GST_OBJECT_LOCK (basesrc);
- oldpool = priv->pool;
- priv->pool = pool;
-
- oldalloc = priv->allocator;
- priv->allocator = allocator;
-
- if (priv->pool)
- gst_object_ref (priv->pool);
- if (priv->allocator)
- gst_object_ref (priv->allocator);
-
- if (params)
- priv->params = *params;
- else
- gst_allocation_params_init (&priv->params);
- GST_OBJECT_UNLOCK (basesrc);
-
- if (oldpool) {
- /* only deactivate if the pool is not the one we're using */
- if (oldpool != pool) {
- GST_DEBUG_OBJECT (basesrc, "deactivate old pool");
- gst_buffer_pool_set_active (oldpool, FALSE);
- }
- gst_object_unref (oldpool);
- }
- if (oldalloc) {
- gst_object_unref (oldalloc);
- }
- return TRUE;
-
- /* ERRORS */
-activate_failed:
- {
- GST_ERROR_OBJECT (basesrc, "failed to activate bufferpool.");
- return FALSE;
- }
-}
-
-static void
-gst_base_src_set_pool_flushing (GstBaseSrc * basesrc, gboolean flushing)
-{
- GstBaseSrcPrivate *priv = basesrc->priv;
- GstBufferPool *pool;
-
- GST_OBJECT_LOCK (basesrc);
- if ((pool = priv->pool))
- pool = gst_object_ref (pool);
- GST_OBJECT_UNLOCK (basesrc);
-
- if (pool) {
- gst_buffer_pool_set_flushing (pool, flushing);
- gst_object_unref (pool);
- }
-}
-
-
-static gboolean
-gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, GstQuery * query)
-{
- GstCaps *outcaps;
- GstBufferPool *pool;
- guint size, min, max;
- GstAllocator *allocator;
- GstAllocationParams params;
- GstStructure *config;
- gboolean update_allocator;
-
- gst_query_parse_allocation (query, &outcaps, NULL);
-
- /* we got configuration from our peer or the decide_allocation method,
- * parse them */
- if (gst_query_get_n_allocation_params (query) > 0) {
- /* try the allocator */
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- update_allocator = TRUE;
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- update_allocator = FALSE;
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0) {
- gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
-
- if (pool == NULL) {
- /* no pool, we can make our own */
- GST_DEBUG_OBJECT (basesrc, "no pool, making new pool");
- pool = gst_buffer_pool_new ();
- }
- } else {
- pool = NULL;
- size = min = max = 0;
- }
-
- /* now configure */
- if (pool) {
- config = gst_buffer_pool_get_config (pool);
- gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
- gst_buffer_pool_config_set_allocator (config, allocator, &params);
-
- /* buffer pool may have to do some changes */
- if (!gst_buffer_pool_set_config (pool, config)) {
- config = gst_buffer_pool_get_config (pool);
-
- /* If change are not acceptable, fallback to generic pool */
- if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
- max)) {
- GST_DEBUG_OBJECT (basesrc, "unsupported pool, making new pool");
-
- gst_object_unref (pool);
- pool = gst_buffer_pool_new ();
- gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
- gst_buffer_pool_config_set_allocator (config, allocator, &params);
- }
-
- if (!gst_buffer_pool_set_config (pool, config))
- goto config_failed;
- }
- }
-
- if (update_allocator)
- gst_query_set_nth_allocation_param (query, 0, allocator, &params);
- else
- gst_query_add_allocation_param (query, allocator, &params);
- if (allocator)
- gst_object_unref (allocator);
-
- if (pool) {
- gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
- gst_object_unref (pool);
- }
-
- return TRUE;
-
-config_failed:
- GST_ELEMENT_ERROR (basesrc, RESOURCE, SETTINGS,
- ("Failed to configure the buffer pool"),
- ("Configuration is most likely invalid, please report this issue."));
- gst_object_unref (pool);
- return FALSE;
-}
-
-static gboolean
-gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps)
-{
- GstBaseSrcClass *bclass;
- gboolean result = TRUE;
- GstQuery *query;
- GstBufferPool *pool = NULL;
- GstAllocator *allocator = NULL;
- GstAllocationParams params;
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
-
- /* make query and let peer pad answer, we don't really care if it worked or
- * not, if it failed, the allocation query would contain defaults and the
- * subclass would then set better values if needed */
- query = gst_query_new_allocation (caps, TRUE);
- if (!gst_pad_peer_query (basesrc->srcpad, query)) {
- /* not a problem, just debug a little */
- GST_DEBUG_OBJECT (basesrc, "peer ALLOCATION query failed");
- }
-
- g_assert (bclass->decide_allocation != NULL);
- result = bclass->decide_allocation (basesrc, query);
-
- GST_DEBUG_OBJECT (basesrc, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
- query);
-
- if (!result)
- goto no_decide_allocation;
-
- /* we got configuration from our peer or the decide_allocation method,
- * parse them */
- if (gst_query_get_n_allocation_params (query) > 0) {
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0)
- gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
-
- result = gst_base_src_set_allocation (basesrc, pool, allocator, &params);
-
- if (allocator)
- gst_object_unref (allocator);
- if (pool)
- gst_object_unref (pool);
-
- gst_query_unref (query);
-
- return result;
-
- /* Errors */
-no_decide_allocation:
- {
- GST_WARNING_OBJECT (basesrc, "Subclass failed to decide allocation");
- gst_query_unref (query);
-
- return result;
- }
-}
-
-/* default negotiation code.
- *
- * Take intersection between src and sink pads, take first
- * caps and fixate.
- */
-static gboolean
-gst_base_src_default_negotiate (GstBaseSrc * basesrc)
-{
- GstCaps *thiscaps;
- GstCaps *caps = NULL;
- GstCaps *peercaps = NULL;
- gboolean result = FALSE;
-
- /* first see what is possible on our source pad */
- thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
- GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
- /* nothing or anything is allowed, we're done */
- if (thiscaps == NULL || gst_caps_is_any (thiscaps))
- goto no_nego_needed;
-
- if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
- goto no_caps;
-
- /* get the peer caps */
- peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), thiscaps);
- GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
- if (peercaps) {
- /* The result is already a subset of our caps */
- caps = peercaps;
- gst_caps_unref (thiscaps);
- } else {
- /* no peer, work with our own caps then */
- caps = thiscaps;
- }
- if (caps && !gst_caps_is_empty (caps)) {
- /* now fixate */
- GST_DEBUG_OBJECT (basesrc, "have caps: %" GST_PTR_FORMAT, caps);
- if (gst_caps_is_any (caps)) {
- GST_DEBUG_OBJECT (basesrc, "any caps, we stop");
- /* hmm, still anything, so element can do anything and
- * nego is not needed */
- result = TRUE;
- } else {
- caps = gst_base_src_fixate (basesrc, caps);
- GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
- if (gst_caps_is_fixed (caps)) {
- /* yay, fixed caps, use those then, it's possible that the subclass does
- * not accept this caps after all and we have to fail. */
- result = gst_base_src_set_caps (basesrc, caps);
- }
- }
- gst_caps_unref (caps);
- } else {
- if (caps)
- gst_caps_unref (caps);
- GST_DEBUG_OBJECT (basesrc, "no common caps");
- }
- return result;
-
-no_nego_needed:
- {
- GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
- if (thiscaps)
- gst_caps_unref (thiscaps);
- return TRUE;
- }
-no_caps:
- {
- GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
- ("No supported formats found"),
- ("This element did not produce valid caps"));
- if (thiscaps)
- gst_caps_unref (thiscaps);
- return TRUE;
- }
-}
-
-static gboolean
-gst_base_src_negotiate_unlocked (GstBaseSrc * basesrc)
-{
- GstBaseSrcClass *bclass;
- gboolean result;
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
-
- GST_DEBUG_OBJECT (basesrc, "starting negotiation");
-
- if (G_LIKELY (bclass->negotiate))
- result = bclass->negotiate (basesrc);
- else
- result = TRUE;
-
- if (G_LIKELY (result)) {
- GstCaps *caps;
-
- caps = gst_pad_get_current_caps (basesrc->srcpad);
-
- result = gst_base_src_prepare_allocation (basesrc, caps);
-
- if (caps)
- gst_caps_unref (caps);
- }
- return result;
-}
-
-/**
- * gst_base_src_negotiate:
- * @src: base source instance
- *
- * Negotiates src pad caps with downstream elements.
- * Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
- * if #GstBaseSrcClass::negotiate fails.
- *
- * Do not call this in the #GstBaseSrcClass::fill vmethod. Call this in
- * #GstBaseSrcClass::create or in #GstBaseSrcClass::alloc, _before_ any
- * buffer is allocated.
- *
- * Returns: %TRUE if the negotiation succeeded, else %FALSE.
- *
- * Since: 1.18
- */
-gboolean
-gst_base_src_negotiate (GstBaseSrc * src)
-{
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
-
- GST_PAD_STREAM_LOCK (src->srcpad);
- gst_pad_check_reconfigure (src->srcpad);
- ret = gst_base_src_negotiate_unlocked (src);
- if (!ret)
- gst_pad_mark_reconfigure (src->srcpad);
- GST_PAD_STREAM_UNLOCK (src->srcpad);
-
- return ret;
-}
-
-static gboolean
-gst_base_src_start (GstBaseSrc * basesrc)
-{
- GstBaseSrcClass *bclass;
- gboolean result;
-
- GST_LIVE_LOCK (basesrc);
-
- GST_OBJECT_LOCK (basesrc);
- if (GST_BASE_SRC_IS_STARTING (basesrc))
- goto was_starting;
- if (GST_BASE_SRC_IS_STARTED (basesrc))
- goto was_started;
-
- basesrc->priv->start_result = GST_FLOW_FLUSHING;
- GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTING);
- gst_segment_init (&basesrc->segment, basesrc->segment.format);
- GST_OBJECT_UNLOCK (basesrc);
-
- basesrc->num_buffers_left = basesrc->num_buffers;
- basesrc->running = FALSE;
- basesrc->priv->segment_pending = FALSE;
- basesrc->priv->segment_seqnum = gst_util_seqnum_next ();
- basesrc->priv->forced_eos = FALSE;
- GST_LIVE_UNLOCK (basesrc);
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
- if (bclass->start)
- result = bclass->start (basesrc);
- else
- result = TRUE;
-
- if (!result)
- goto could_not_start;
-
- if (!gst_base_src_is_async (basesrc)) {
- gst_base_src_start_complete (basesrc, GST_FLOW_OK);
- /* not really waiting here, we call this to get the result
- * from the start_complete call */
- result = gst_base_src_start_wait (basesrc) == GST_FLOW_OK;
- }
-
- return result;
-
- /* ERROR */
-was_starting:
- {
- GST_DEBUG_OBJECT (basesrc, "was starting");
- GST_OBJECT_UNLOCK (basesrc);
- GST_LIVE_UNLOCK (basesrc);
- return TRUE;
- }
-was_started:
- {
- GST_DEBUG_OBJECT (basesrc, "was started");
- GST_OBJECT_UNLOCK (basesrc);
- GST_LIVE_UNLOCK (basesrc);
- return TRUE;
- }
-could_not_start:
- {
- GST_DEBUG_OBJECT (basesrc, "could not start");
- /* subclass is supposed to post a message but we post one as a fallback
- * just in case. We don't have to call _stop. */
- GST_ELEMENT_ERROR (basesrc, CORE, STATE_CHANGE, (NULL),
- ("Failed to start"));
- gst_base_src_start_complete (basesrc, GST_FLOW_ERROR);
- return FALSE;
- }
-}
-
-/**
- * gst_base_src_start_complete:
- * @basesrc: base source instance
- * @ret: a #GstFlowReturn
- *
- * Complete an asynchronous start operation. When the subclass overrides the
- * start method, it should call gst_base_src_start_complete() when the start
- * operation completes either from the same thread or from an asynchronous
- * helper thread.
- */
-void
-gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
-{
- gboolean have_size;
- guint64 size;
- gboolean seekable;
- GstFormat format;
- GstPadMode mode;
- GstEvent *event;
-
- if (ret != GST_FLOW_OK)
- goto error;
-
- GST_DEBUG_OBJECT (basesrc, "starting source");
- format = basesrc->segment.format;
-
- /* figure out the size */
- have_size = FALSE;
- size = -1;
- if (format == GST_FORMAT_BYTES) {
- GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc);
-
- if (bclass->get_size) {
- if (!(have_size = bclass->get_size (basesrc, &size)))
- size = -1;
- }
- GST_DEBUG_OBJECT (basesrc, "setting size %" G_GUINT64_FORMAT, size);
- /* only update the size when operating in bytes, subclass is supposed
- * to set duration in the start method for other formats */
- GST_OBJECT_LOCK (basesrc);
- basesrc->segment.duration = size;
- GST_OBJECT_UNLOCK (basesrc);
- }
-
- GST_DEBUG_OBJECT (basesrc,
- "format: %s, have size: %d, size: %" G_GUINT64_FORMAT ", duration: %"
- G_GINT64_FORMAT, gst_format_get_name (format), have_size, size,
- basesrc->segment.duration);
-
- seekable = gst_base_src_seekable (basesrc);
- GST_DEBUG_OBJECT (basesrc, "is seekable: %d", seekable);
-
- /* update for random access flag */
- basesrc->random_access = seekable && format == GST_FORMAT_BYTES;
-
- GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access);
-
- gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (basesrc));
-
- GST_OBJECT_LOCK (basesrc->srcpad);
- mode = GST_PAD_MODE (basesrc->srcpad);
- GST_OBJECT_UNLOCK (basesrc->srcpad);
-
- /* take the stream lock here, we only want to let the task run when we have
- * set the STARTED flag */
- GST_PAD_STREAM_LOCK (basesrc->srcpad);
- switch (mode) {
- case GST_PAD_MODE_PUSH:
- /* do initial seek, which will start the task */
- GST_OBJECT_LOCK (basesrc);
- event = basesrc->pending_seek;
- basesrc->pending_seek = NULL;
- GST_OBJECT_UNLOCK (basesrc);
-
- /* The perform seek code will start the task when finished. We don't have to
- * unlock the streaming thread because it is not running yet */
- if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
- goto seek_failed;
-
- if (event)
- gst_event_unref (event);
- break;
- case GST_PAD_MODE_PULL:
- /* if not random_access, we cannot operate in pull mode for now */
- if (G_UNLIKELY (!basesrc->random_access))
- goto no_get_range;
- break;
- default:
- goto not_activated_yet;
- break;
- }
-
- GST_OBJECT_LOCK (basesrc);
- GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTED);
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
- basesrc->priv->start_result = ret;
- GST_ASYNC_SIGNAL (basesrc);
- GST_OBJECT_UNLOCK (basesrc);
-
- GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
-
- return;
-
-seek_failed:
- {
- GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
- GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
- gst_base_src_stop (basesrc);
- if (event)
- gst_event_unref (event);
- ret = GST_FLOW_ERROR;
- goto error;
- }
-no_get_range:
- {
- GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
- gst_base_src_stop (basesrc);
- GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
- ret = GST_FLOW_ERROR;
- goto error;
- }
-not_activated_yet:
- {
- GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
- gst_base_src_stop (basesrc);
- GST_WARNING_OBJECT (basesrc, "pad not activated yet");
- ret = GST_FLOW_ERROR;
- goto error;
- }
-error:
- {
- GST_OBJECT_LOCK (basesrc);
- basesrc->priv->start_result = ret;
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
- GST_ASYNC_SIGNAL (basesrc);
- GST_OBJECT_UNLOCK (basesrc);
- return;
- }
-}
-
-/**
- * gst_base_src_start_wait:
- * @basesrc: base source instance
- *
- * Wait until the start operation completes.
- *
- * Returns: a #GstFlowReturn.
- */
-GstFlowReturn
-gst_base_src_start_wait (GstBaseSrc * basesrc)
-{
- GstFlowReturn result;
-
- GST_OBJECT_LOCK (basesrc);
- while (GST_BASE_SRC_IS_STARTING (basesrc)) {
- GST_ASYNC_WAIT (basesrc);
- }
- result = basesrc->priv->start_result;
- GST_OBJECT_UNLOCK (basesrc);
-
- GST_DEBUG_OBJECT (basesrc, "got %s", gst_flow_get_name (result));
-
- return result;
-}
-
-static gboolean
-gst_base_src_stop (GstBaseSrc * basesrc)
-{
- GstBaseSrcClass *bclass;
- gboolean result = TRUE;
-
- GST_DEBUG_OBJECT (basesrc, "stopping source");
-
- /* flush all */
- gst_base_src_set_flushing (basesrc, TRUE);
-
- /* stop the task */
- gst_pad_stop_task (basesrc->srcpad);
- /* stop flushing, this will balance unlock/unlock_stop calls */
- gst_base_src_set_flushing (basesrc, FALSE);
-
- GST_OBJECT_LOCK (basesrc);
- if (!GST_BASE_SRC_IS_STARTED (basesrc) && !GST_BASE_SRC_IS_STARTING (basesrc))
- goto was_stopped;
-
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
- GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
- basesrc->priv->start_result = GST_FLOW_FLUSHING;
- GST_ASYNC_SIGNAL (basesrc);
- GST_OBJECT_UNLOCK (basesrc);
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
- if (bclass->stop)
- result = bclass->stop (basesrc);
-
- if (basesrc->priv->pending_bufferlist != NULL) {
- gst_buffer_list_unref (basesrc->priv->pending_bufferlist);
- basesrc->priv->pending_bufferlist = NULL;
- }
-
- gst_base_src_set_allocation (basesrc, NULL, NULL, NULL);
-
- return result;
-
-was_stopped:
- {
- GST_DEBUG_OBJECT (basesrc, "was stopped");
- GST_OBJECT_UNLOCK (basesrc);
- return TRUE;
- }
-}
-
-/* start or stop flushing dataprocessing
- */
-static gboolean
-gst_base_src_set_flushing (GstBaseSrc * basesrc, gboolean flushing)
-{
- GstBaseSrcClass *bclass;
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
-
- GST_DEBUG_OBJECT (basesrc, "flushing %d", flushing);
-
- if (flushing) {
- gst_base_src_set_pool_flushing (basesrc, TRUE);
- /* unlock any subclasses to allow turning off the streaming thread */
- if (bclass->unlock)
- bclass->unlock (basesrc);
- }
-
- /* the live lock is released when we are blocked, waiting for playing,
- * when we sync to the clock or creating a buffer */
- GST_LIVE_LOCK (basesrc);
- basesrc->priv->flushing = flushing;
- if (flushing) {
- /* clear pending EOS if any */
- if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
- GST_OBJECT_LOCK (basesrc);
- CLEAR_PENDING_EOS (basesrc);
- basesrc->priv->forced_eos = FALSE;
- GST_OBJECT_UNLOCK (basesrc);
- }
-
- /* unblock clock sync (if any) or any other blocking thing */
- if (basesrc->clock_id)
- gst_clock_id_unschedule (basesrc->clock_id);
- } else {
- gst_base_src_set_pool_flushing (basesrc, FALSE);
-
- /* Drop all delayed events */
- GST_OBJECT_LOCK (basesrc);
- if (basesrc->priv->pending_events) {
- g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref,
- NULL);
- g_list_free (basesrc->priv->pending_events);
- basesrc->priv->pending_events = NULL;
- g_atomic_int_set (&basesrc->priv->have_events, FALSE);
- }
- GST_OBJECT_UNLOCK (basesrc);
- }
-
- GST_LIVE_SIGNAL (basesrc);
- GST_LIVE_UNLOCK (basesrc);
-
- if (!flushing) {
- /* Now wait for the stream lock to be released and clear our unlock request */
- GST_PAD_STREAM_LOCK (basesrc->srcpad);
- if (bclass->unlock_stop)
- bclass->unlock_stop (basesrc);
- GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
- }
-
- return TRUE;
-}
-
-/* the purpose of this function is to make sure that a live source blocks in the
- * LIVE lock or leaves the LIVE lock and continues playing. */
-static gboolean
-gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play)
-{
- /* we are now able to grab the LIVE lock, when we get it, we can be
- * waiting for PLAYING while blocked in the LIVE cond or we can be waiting
- * for the clock. */
- GST_LIVE_LOCK (basesrc);
- GST_DEBUG_OBJECT (basesrc, "unschedule clock");
-
- /* unblock clock sync (if any) */
- if (basesrc->clock_id)
- gst_clock_id_unschedule (basesrc->clock_id);
-
- /* configure what to do when we get to the LIVE lock. */
- GST_DEBUG_OBJECT (basesrc, "live running %d", live_play);
- basesrc->live_running = live_play;
-
- if (live_play) {
- gboolean start;
-
- /* for live sources we restart the timestamp correction */
- GST_OBJECT_LOCK (basesrc);
- basesrc->priv->latency = -1;
- GST_OBJECT_UNLOCK (basesrc);
- /* have to restart the task in case it stopped because of the unlock when
- * we went to PAUSED. Only do this if we operating in push mode. */
- GST_OBJECT_LOCK (basesrc->srcpad);
- start = (GST_PAD_MODE (basesrc->srcpad) == GST_PAD_MODE_PUSH);
- GST_OBJECT_UNLOCK (basesrc->srcpad);
- if (start)
- gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop,
- basesrc->srcpad, NULL);
- GST_DEBUG_OBJECT (basesrc, "signal");
- GST_LIVE_SIGNAL (basesrc);
- }
- GST_LIVE_UNLOCK (basesrc);
-
- return TRUE;
-}
-
-static gboolean
-gst_base_src_activate_push (GstPad * pad, GstObject * parent, gboolean active)
-{
- GstBaseSrc *basesrc;
-
- basesrc = GST_BASE_SRC (parent);
-
- /* prepare subclass first */
- if (active) {
- GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
-
- if (G_UNLIKELY (!basesrc->can_activate_push))
- goto no_push_activation;
-
- if (G_UNLIKELY (!gst_base_src_start (basesrc)))
- goto error_start;
- } else {
- GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
- /* now we can stop the source */
- if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
- goto error_stop;
- }
- return TRUE;
-
- /* ERRORS */
-no_push_activation:
- {
- GST_WARNING_OBJECT (basesrc, "Subclass disabled push-mode activation");
- return FALSE;
- }
-error_start:
- {
- GST_WARNING_OBJECT (basesrc, "Failed to start in push mode");
- return FALSE;
- }
-error_stop:
- {
- GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode");
- return FALSE;
- }
-}
-
-static gboolean
-gst_base_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active)
-{
- GstBaseSrc *basesrc;
-
- basesrc = GST_BASE_SRC (parent);
-
- /* prepare subclass first */
- if (active) {
- GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
- if (G_UNLIKELY (!gst_base_src_start (basesrc)))
- goto error_start;
- } else {
- GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
- if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
- goto error_stop;
- }
- return TRUE;
-
- /* ERRORS */
-error_start:
- {
- GST_ERROR_OBJECT (basesrc, "Failed to start in pull mode");
- return FALSE;
- }
-error_stop:
- {
- GST_ERROR_OBJECT (basesrc, "Failed to stop in pull mode");
- return FALSE;
- }
-}
-
-static gboolean
-gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active)
-{
- gboolean res;
- GstBaseSrc *src = GST_BASE_SRC (parent);
-
- src->priv->stream_start_pending = FALSE;
-
- GST_DEBUG_OBJECT (pad, "activating in mode %d", mode);
-
- switch (mode) {
- case GST_PAD_MODE_PULL:
- res = gst_base_src_activate_pull (pad, parent, active);
- break;
- case GST_PAD_MODE_PUSH:
- src->priv->stream_start_pending = active;
- res = gst_base_src_activate_push (pad, parent, active);
- break;
- default:
- GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
- res = FALSE;
- break;
- }
- return res;
-}
-
-
-static GstStateChangeReturn
-gst_base_src_change_state (GstElement * element, GstStateChange transition)
-{
- GstBaseSrc *basesrc;
- GstStateChangeReturn result;
- gboolean no_preroll = FALSE;
-
- basesrc = GST_BASE_SRC (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- no_preroll = gst_base_src_is_live (basesrc);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- GST_DEBUG_OBJECT (basesrc, "PAUSED->PLAYING");
- if (gst_base_src_is_live (basesrc)) {
- /* now we can start playback */
- gst_base_src_set_playing (basesrc, TRUE);
- }
- break;
- default:
- break;
- }
-
- if ((result =
- GST_ELEMENT_CLASS (parent_class)->change_state (element,
- transition)) == GST_STATE_CHANGE_FAILURE)
- goto failure;
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- GST_DEBUG_OBJECT (basesrc, "PLAYING->PAUSED");
- if (gst_base_src_is_live (basesrc)) {
- /* make sure we block in the live cond in PAUSED */
- gst_base_src_set_playing (basesrc, FALSE);
- no_preroll = TRUE;
- }
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- {
- /* we don't need to unblock anything here, the pad deactivation code
- * already did this */
- if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
- GST_OBJECT_LOCK (basesrc);
- CLEAR_PENDING_EOS (basesrc);
- GST_OBJECT_UNLOCK (basesrc);
- }
- gst_event_replace (&basesrc->pending_seek, NULL);
- break;
- }
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
- result = GST_STATE_CHANGE_NO_PREROLL;
-
- return result;
-
- /* ERRORS */
-failure:
- {
- GST_DEBUG_OBJECT (basesrc, "parent failed state change");
- return result;
- }
-}
-
-/**
- * gst_base_src_get_buffer_pool:
- * @src: a #GstBaseSrc
- *
- * Returns: (nullable) (transfer full): the instance of the #GstBufferPool used
- * by the src; unref it after usage.
- */
-GstBufferPool *
-gst_base_src_get_buffer_pool (GstBaseSrc * src)
-{
- GstBufferPool *ret = NULL;
-
- g_return_val_if_fail (GST_IS_BASE_SRC (src), NULL);
-
- GST_OBJECT_LOCK (src);
- if (src->priv->pool)
- ret = gst_object_ref (src->priv->pool);
- GST_OBJECT_UNLOCK (src);
-
- return ret;
-}
-
-/**
- * gst_base_src_get_allocator:
- * @src: a #GstBaseSrc
- * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
- * used
- * @params: (out caller-allocates) (optional): the #GstAllocationParams of @allocator
- *
- * Lets #GstBaseSrc sub-classes to know the memory @allocator
- * used by the base class and its @params.
- *
- * Unref the @allocator after usage.
- */
-void
-gst_base_src_get_allocator (GstBaseSrc * src,
- GstAllocator ** allocator, GstAllocationParams * params)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
-
- GST_OBJECT_LOCK (src);
- if (allocator)
- *allocator = src->priv->allocator ?
- gst_object_ref (src->priv->allocator) : NULL;
-
- if (params)
- *params = src->priv->params;
- GST_OBJECT_UNLOCK (src);
-}
-
-/**
- * gst_base_src_submit_buffer_list:
- * @src: a #GstBaseSrc
- * @buffer_list: (transfer full): a #GstBufferList
- *
- * Subclasses can call this from their create virtual method implementation
- * to submit a buffer list to be pushed out later. This is useful in
- * cases where the create function wants to produce multiple buffers to be
- * pushed out in one go in form of a #GstBufferList, which can reduce overhead
- * drastically, especially for packetised inputs (for data streams where
- * the packetisation/chunking is not important it is usually more efficient
- * to return larger buffers instead).
- *
- * Subclasses that use this function from their create function must return
- * %GST_FLOW_OK and no buffer from their create virtual method implementation.
- * If a buffer is returned after a buffer list has also been submitted via this
- * function the behaviour is undefined.
- *
- * Subclasses must only call this function once per create function call and
- * subclasses must only call this function when the source operates in push
- * mode.
- *
- * Since: 1.14
- */
-void
-gst_base_src_submit_buffer_list (GstBaseSrc * src, GstBufferList * buffer_list)
-{
- g_return_if_fail (GST_IS_BASE_SRC (src));
- g_return_if_fail (GST_IS_BUFFER_LIST (buffer_list));
- g_return_if_fail (BASE_SRC_HAS_PENDING_BUFFER_LIST (src) == FALSE);
-
- /* we need it to be writable later in get_range() where we use get_writable */
- src->priv->pending_bufferlist = gst_buffer_list_make_writable (buffer_list);
-
- GST_LOG_OBJECT (src, "%u buffers submitted in buffer list",
- gst_buffer_list_length (buffer_list));
-}
diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h
deleted file mode 100644
index 04304bfd06..0000000000
--- a/libs/gst/base/gstbasesrc.h
+++ /dev/null
@@ -1,334 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_SRC_H__
-#define __GST_BASE_SRC_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.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(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_SRC))
-#define GST_BASE_SRC_CAST(obj) ((GstBaseSrc *)(obj))
-
-/**
- * GstBaseSrcFlags:
- * @GST_BASE_SRC_FLAG_STARTING: has source is starting
- * @GST_BASE_SRC_FLAG_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_FLAG_STARTING = (GST_ELEMENT_FLAG_LAST << 0),
- GST_BASE_SRC_FLAG_STARTED = (GST_ELEMENT_FLAG_LAST << 1),
- /* padding */
- GST_BASE_SRC_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 6)
-} GstBaseSrcFlags;
-
-#define GST_BASE_SRC_IS_STARTING(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTING)
-#define GST_BASE_SRC_IS_STARTED(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTED)
-
-typedef struct _GstBaseSrc GstBaseSrc;
-typedef struct _GstBaseSrcClass GstBaseSrcClass;
-typedef struct _GstBaseSrcPrivate GstBaseSrcPrivate;
-
-/**
- * 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) */
- guint blocksize; /* size of buffers when operating push based */
- gboolean can_activate_push; /* some scheduling properties */
- gboolean random_access;
-
- GstClockID clock_id; /* for syncing */
-
- /* MT-protected (with STREAM_LOCK *and* OBJECT_LOCK) */
- GstSegment segment;
- /* MT-protected (with STREAM_LOCK) */
- gboolean need_newsegment;
-
- gint num_buffers;
- gint num_buffers_left;
-
-#ifndef GST_REMOVE_DEPRECATED
- gboolean typefind; /* unused */
-#endif
-
- gboolean running;
- GstEvent *pending_seek;
-
- GstBaseSrcPrivate *priv;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-/**
- * GstBaseSrcClass:
- * @parent_class: Element parent class
- * @get_caps: Called to get the caps to report
- * @negotiate: Negotiated the caps with the peer.
- * @fixate: Called during negotiation if caps need fixating. Implement instead of
- * setting a fixate function on the source pad.
- * @set_caps: Notify subclass of changed output caps
- * @decide_allocation: configure the allocation query
- * @start: Start processing. Subclasses should open resources and prepare
- * to produce data. Implementation should call gst_base_src_start_complete()
- * when the operation completes, either from the current thread or any other
- * thread that finishes the start operation asynchronously.
- * @stop: Stop processing. Subclasses should use this to close resources.
- * @get_times: Given a buffer, return the start and stop time when it
- * should be pushed out. The base class will sync on the clock using
- * these times.
- * @get_size: Return the total size of the resource, in the format set by
- * gst_base_src_set_format().
- * @is_seekable: Check if the source can seek
- * @prepare_seek_segment: Prepare the #GstSegment that will be passed to the
- * #GstBaseSrcClass::do_seek vmethod for executing a seek
- * request. Sub-classes should override this if they support seeking in
- * formats other than the configured native format. By default, it tries to
- * convert the seek arguments to the configured native format and prepare a
- * segment in that format.
- * @do_seek: Perform seeking on the resource to the indicated segment.
- * @unlock: Unlock any pending access to the resource. Subclasses should unblock
- * any blocked function ASAP. In particular, any `create()` function in
- * progress should be unblocked and should return GST_FLOW_FLUSHING. Any
- * future #GstBaseSrcClass::create function call should also return
- * GST_FLOW_FLUSHING until the #GstBaseSrcClass::unlock_stop function has
- * been called.
- * @unlock_stop: Clear the previous unlock request. Subclasses should clear any
- * state they set during #GstBaseSrcClass::unlock, such as clearing command
- * queues.
- * @query: Handle a requested query.
- * @event: Override this to implement custom event handling.
- * @create: Ask the subclass to create a buffer with offset and size. When the
- * subclass returns GST_FLOW_OK, it MUST return a buffer of the requested size
- * unless fewer bytes are available because an EOS condition is near. No
- * buffer should be returned when the return value is different from
- * GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the end of
- * stream is reached. The default implementation will call
- * #GstBaseSrcClass::alloc and then call #GstBaseSrcClass::fill.
- * @alloc: Ask the subclass to allocate a buffer with for offset and size. The
- * default implementation will create a new buffer from the negotiated allocator.
- * @fill: Ask the subclass to fill the buffer with data for offset and size. The
- * passed buffer is guaranteed to hold the requested amount of bytes.
- *
- * Subclasses can override any of the available virtual methods or not, as
- * needed. At the minimum, the @create method should be overridden to produce
- * buffers.
- */
-struct _GstBaseSrcClass {
- GstElementClass parent_class;
-
- /*< public >*/
- /* virtual methods for subclasses */
-
- /**
- * GstBaseSrcClass::get_caps:
- * @filter: (in) (nullable):
- *
- * Called to get the caps to report.
- */
- GstCaps* (*get_caps) (GstBaseSrc *src, GstCaps *filter);
- /* decide on caps */
- gboolean (*negotiate) (GstBaseSrc *src);
- /* called if, in negotiation, caps need fixating */
- GstCaps * (*fixate) (GstBaseSrc *src, GstCaps *caps);
- /* notify the subclass of new caps */
- gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps);
-
- /* setup allocation query */
- gboolean (*decide_allocation) (GstBaseSrc *src, GstQuery *query);
-
- /* start and stop processing, ideal for opening/closing the resource */
- gboolean (*start) (GstBaseSrc *src);
- gboolean (*stop) (GstBaseSrc *src);
-
- /**
- * GstBaseSrcClass::get_times:
- * @start: (out):
- * @end: (out):
- *
- * Given @buffer, return @start and @end 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 the format set by
- * gst_base_src_set_format() */
- gboolean (*get_size) (GstBaseSrc *src, guint64 *size);
-
- /* check if the resource is seekable */
- gboolean (*is_seekable) (GstBaseSrc *src);
-
- /* Prepare the segment on which to perform do_seek(), converting to the
- * current basesrc format. */
- gboolean (*prepare_seek_segment) (GstBaseSrc *src, GstEvent *seek,
- GstSegment *segment);
- /* notify subclasses of a seek */
- gboolean (*do_seek) (GstBaseSrc *src, GstSegment *segment);
-
- /* unlock any pending access to the resource. subclasses should unlock
- * any function ASAP. */
- gboolean (*unlock) (GstBaseSrc *src);
- /* Clear any pending unlock request, as we succeeded in unlocking */
- gboolean (*unlock_stop) (GstBaseSrc *src);
-
- /* notify subclasses of a query */
- gboolean (*query) (GstBaseSrc *src, GstQuery *query);
-
- /* notify subclasses of an event */
- gboolean (*event) (GstBaseSrc *src, GstEvent *event);
-
- /**
- * GstBaseSrcClass::create:
- * @buf: (out):
- *
- * Ask the subclass to create a buffer with @offset and @size, the default
- * implementation will call alloc and fill.
- */
- GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size,
- GstBuffer **buf);
- /* ask the subclass to allocate an output buffer. The default implementation
- * will use the negotiated allocator. */
- GstFlowReturn (*alloc) (GstBaseSrc *src, guint64 offset, guint size,
- GstBuffer **buf);
- /* ask the subclass to fill the buffer with data from offset and size */
- GstFlowReturn (*fill) (GstBaseSrc *src, guint64 offset, guint size,
- GstBuffer *buf);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
-};
-
-GST_BASE_API
-GType gst_base_src_get_type (void);
-
-GST_BASE_API
-GstFlowReturn gst_base_src_wait_playing (GstBaseSrc *src);
-
-GST_BASE_API
-void gst_base_src_set_live (GstBaseSrc *src, gboolean live);
-
-GST_BASE_API
-gboolean gst_base_src_is_live (GstBaseSrc *src);
-
-GST_BASE_API
-void gst_base_src_set_format (GstBaseSrc *src, GstFormat format);
-
-GST_BASE_API
-void gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic);
-
-GST_BASE_API
-void gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos);
-
-GST_BASE_API
-void gst_base_src_set_async (GstBaseSrc *src, gboolean async);
-
-GST_BASE_API
-gboolean gst_base_src_is_async (GstBaseSrc *src);
-
-GST_BASE_API
-gboolean gst_base_src_negotiate (GstBaseSrc *src);
-
-GST_BASE_API
-void gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret);
-
-GST_BASE_API
-GstFlowReturn gst_base_src_start_wait (GstBaseSrc * basesrc);
-
-GST_BASE_API
-gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live,
- GstClockTime * min_latency,
- GstClockTime * max_latency);
-GST_BASE_API
-void gst_base_src_set_blocksize (GstBaseSrc *src, guint blocksize);
-
-GST_BASE_API
-guint gst_base_src_get_blocksize (GstBaseSrc *src);
-
-GST_BASE_API
-void gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean timestamp);
-
-GST_BASE_API
-gboolean gst_base_src_get_do_timestamp (GstBaseSrc *src);
-
-GST_BASE_API
-gboolean gst_base_src_new_seamless_segment (GstBaseSrc *src, gint64 start, gint64 stop, gint64 time);
-
-GST_BASE_API
-gboolean gst_base_src_new_segment (GstBaseSrc *src,
- const GstSegment * segment);
-
-GST_BASE_API
-gboolean gst_base_src_set_caps (GstBaseSrc *src, GstCaps *caps);
-
-GST_BASE_API
-GstBufferPool * gst_base_src_get_buffer_pool (GstBaseSrc *src);
-
-GST_BASE_API
-void gst_base_src_get_allocator (GstBaseSrc *src,
- GstAllocator **allocator,
- GstAllocationParams *params);
-
-GST_BASE_API
-void gst_base_src_submit_buffer_list (GstBaseSrc * src,
- GstBufferList * buffer_list);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSrc, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_BASE_SRC_H__ */
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
deleted file mode 100644
index e4e7ee6415..0000000000
--- a/libs/gst/base/gstbasetransform.c
+++ /dev/null
@@ -1,2921 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2005 Wim Taymans <wim@fluendo.com>
- * 2005 Andy Wingo <wingo@fluendo.com>
- * 2005 Thomas Vander Stichele <thomas at apestaart dot org>
- * 2008 Wim Taymans <wim.taymans@gmail.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstbasetransform
- * @title: GstBaseTransform
- * @short_description: Base class for simple transform filters
- * @see_also: #GstBaseSrc, #GstBaseSink
- *
- * This base class is for filter elements that process data. Elements
- * that are suitable for implementation using #GstBaseTransform are ones
- * where the size and caps of the output is known entirely from the input
- * caps and buffer sizes. These include elements that directly transform
- * one buffer into another, modify the contents of a buffer in-place, as
- * well as elements that collate multiple input buffers into one output buffer,
- * or that expand one input buffer into multiple output buffers. See below
- * for more concrete use cases.
- *
- * It provides for:
- *
- * * one sinkpad and one srcpad
- * * Possible formats on sink and source pad implemented
- * with custom transform_caps function. By default uses
- * same format on sink and source.
- *
- * * Handles state changes
- * * Does flushing
- * * Push mode
- * * Pull mode if the sub-class transform can operate on arbitrary data
- *
- * # Use Cases
- *
- * ## Passthrough mode
- *
- * * Element has no interest in modifying the buffer. It may want to inspect it,
- * in which case the element should have a transform_ip function. If there
- * is no transform_ip function in passthrough mode, the buffer is pushed
- * intact.
- *
- * * The #GstBaseTransformClass.passthrough_on_same_caps variable
- * will automatically set/unset passthrough based on whether the
- * element negotiates the same caps on both pads.
- *
- * * #GstBaseTransformClass.passthrough_on_same_caps on an element that
- * doesn't implement a transform_caps function is useful for elements that
- * only inspect data (such as level)
- *
- * * Example elements
- *
- * * Level
- * * Videoscale, audioconvert, videoconvert, audioresample in certain modes.
- *
- * ## Modifications in-place - input buffer and output buffer are the same thing.
- *
- * * The element must implement a transform_ip function.
- * * Output buffer size must <= input buffer size
- * * If the always_in_place flag is set, non-writable buffers will be copied
- * and passed to the transform_ip function, otherwise a new buffer will be
- * created and the transform function called.
- *
- * * Incoming writable buffers will be passed to the transform_ip function
- * immediately.
- * * only implementing transform_ip and not transform implies always_in_place = %TRUE
- *
- * * Example elements:
- * * Volume
- * * Audioconvert in certain modes (signed/unsigned conversion)
- * * videoconvert in certain modes (endianness swapping)
- *
- * ## Modifications only to the caps/metadata of a buffer
- *
- * * The element does not require writable data, but non-writable buffers
- * should be subbuffered so that the meta-information can be replaced.
- *
- * * Elements wishing to operate in this mode should replace the
- * prepare_output_buffer method to create subbuffers of the input buffer
- * and set always_in_place to %TRUE
- *
- * * Example elements
- * * Capsfilter when setting caps on outgoing buffers that have
- * none.
- * * identity when it is going to re-timestamp buffers by
- * datarate.
- *
- * ## Normal mode
- * * always_in_place flag is not set, or there is no transform_ip function
- * * Element will receive an input buffer and output buffer to operate on.
- * * Output buffer is allocated by calling the prepare_output_buffer function.
- * * Example elements:
- * * Videoscale, videoconvert, audioconvert when doing
- * scaling/conversions
- *
- * ## Special output buffer allocations
- * * Elements which need to do special allocation of their output buffers
- * beyond allocating output buffers via the negotiated allocator or
- * buffer pool should implement the prepare_output_buffer method.
- *
- * * Example elements:
- * * efence
- *
- * # Sub-class settable flags on GstBaseTransform
- *
- * * passthrough
- *
- * * Implies that in the current configuration, the sub-class is not interested in modifying the buffers.
- * * Elements which are always in passthrough mode whenever the same caps has been negotiated on both pads can set the class variable passthrough_on_same_caps to have this behaviour automatically.
- *
- * * always_in_place
- * * Determines whether a non-writable buffer will be copied before passing
- * to the transform_ip function.
- *
- * * Implied %TRUE if no transform function is implemented.
- * * Implied %FALSE if ONLY transform function is implemented.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "../../../gst/gst_private.h"
-#include "../../../gst/gst-i18n-lib.h"
-#include "../../../gst/glib-compat-private.h"
-#include "gstbasetransform.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_base_transform_debug);
-#define GST_CAT_DEFAULT gst_base_transform_debug
-
-/* BaseTransform signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-#define DEFAULT_PROP_QOS FALSE
-
-enum
-{
- PROP_0,
- PROP_QOS
-};
-
-struct _GstBaseTransformPrivate
-{
- /* Set by sub-class */
- gboolean passthrough;
- gboolean always_in_place;
-
- GstCaps *cache_caps1;
- gsize cache_caps1_size;
- GstCaps *cache_caps2;
- gsize cache_caps2_size;
- gboolean have_same_caps;
-
- gboolean negotiated;
-
- /* QoS *//* with LOCK */
- gboolean qos_enabled;
- gdouble proportion;
- GstClockTime earliest_time;
- /* previous buffer had a discont */
- gboolean discont;
-
- GstPadMode pad_mode;
-
- gboolean gap_aware;
- gboolean prefer_passthrough;
-
- /* QoS stats */
- guint64 processed;
- guint64 dropped;
-
- GstClockTime position_out;
-
- GstBufferPool *pool;
- gboolean pool_active;
- GstAllocator *allocator;
- GstAllocationParams params;
- GstQuery *query;
-};
-
-
-static GstElementClass *parent_class = NULL;
-static gint private_offset = 0;
-
-static void gst_base_transform_class_init (GstBaseTransformClass * klass);
-static void gst_base_transform_init (GstBaseTransform * trans,
- GstBaseTransformClass * klass);
-static GstFlowReturn default_submit_input_buffer (GstBaseTransform * trans,
- gboolean is_discont, GstBuffer * input);
-static GstFlowReturn default_generate_output (GstBaseTransform * trans,
- GstBuffer ** outbuf);
-
-/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
- * method to get to the padtemplates */
-GType
-gst_base_transform_get_type (void)
-{
- static gsize base_transform_type = 0;
-
- if (g_once_init_enter (&base_transform_type)) {
- GType _type;
- static const GTypeInfo base_transform_info = {
- sizeof (GstBaseTransformClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_base_transform_class_init,
- NULL,
- NULL,
- sizeof (GstBaseTransform),
- 0,
- (GInstanceInitFunc) gst_base_transform_init,
- };
-
- _type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);
-
- private_offset =
- g_type_add_instance_private (_type, sizeof (GstBaseTransformPrivate));
-
- g_once_init_leave (&base_transform_type, _type);
- }
- return base_transform_type;
-}
-
-static inline GstBaseTransformPrivate *
-gst_base_transform_get_instance_private (GstBaseTransform * self)
-{
- return (G_STRUCT_MEMBER_P (self, private_offset));
-}
-
-static void gst_base_transform_finalize (GObject * object);
-static void gst_base_transform_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_base_transform_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_base_transform_src_activate_mode (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active);
-static gboolean gst_base_transform_sink_activate_mode (GstPad * pad,
- GstObject * parent, GstPadMode mode, gboolean active);
-static gboolean gst_base_transform_activate (GstBaseTransform * trans,
- gboolean active);
-static gboolean gst_base_transform_get_unit_size (GstBaseTransform * trans,
- GstCaps * caps, gsize * size);
-
-static gboolean gst_base_transform_src_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_base_transform_src_eventfunc (GstBaseTransform * trans,
- GstEvent * event);
-static gboolean gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_base_transform_sink_eventfunc (GstBaseTransform * trans,
- GstEvent * event);
-static GstFlowReturn gst_base_transform_getrange (GstPad * pad,
- GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
-static GstFlowReturn gst_base_transform_chain (GstPad * pad, GstObject * parent,
- GstBuffer * buffer);
-static GstCaps *gst_base_transform_default_transform_caps (GstBaseTransform *
- trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter);
-static GstCaps *gst_base_transform_default_fixate_caps (GstBaseTransform *
- trans, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
-static GstCaps *gst_base_transform_query_caps (GstBaseTransform * trans,
- GstPad * pad, GstCaps * filter);
-static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps);
-static gboolean gst_base_transform_setcaps (GstBaseTransform * trans,
- GstPad * pad, GstCaps * caps);
-static gboolean gst_base_transform_default_decide_allocation (GstBaseTransform
- * trans, GstQuery * query);
-static gboolean gst_base_transform_default_propose_allocation (GstBaseTransform
- * trans, GstQuery * decide_query, GstQuery * query);
-static gboolean gst_base_transform_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-static gboolean gst_base_transform_default_query (GstBaseTransform * trans,
- GstPadDirection direction, GstQuery * query);
-static gboolean gst_base_transform_default_transform_size (GstBaseTransform *
- trans, GstPadDirection direction, GstCaps * caps, gsize size,
- GstCaps * othercaps, gsize * othersize);
-
-static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans,
- GstBuffer * inbuf, GstBuffer ** outbuf);
-static gboolean default_copy_metadata (GstBaseTransform * trans,
- GstBuffer * inbuf, GstBuffer * outbuf);
-static gboolean
-gst_base_transform_default_transform_meta (GstBaseTransform * trans,
- GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf);
-
-/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
-
-
-static void
-gst_base_transform_finalize (GObject * object)
-{
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_base_transform_class_init (GstBaseTransformClass * klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- if (private_offset != 0)
- g_type_class_adjust_private_offset (klass, &private_offset);
-
- GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,
- "basetransform element");
-
- GST_DEBUG ("gst_base_transform_class_init");
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->set_property = gst_base_transform_set_property;
- gobject_class->get_property = gst_base_transform_get_property;
-
- g_object_class_install_property (gobject_class, PROP_QOS,
- g_param_spec_boolean ("qos", "QoS", "Handle Quality-of-Service events",
- DEFAULT_PROP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gobject_class->finalize = gst_base_transform_finalize;
-
- klass->passthrough_on_same_caps = FALSE;
- klass->transform_ip_on_passthrough = TRUE;
-
- klass->transform_caps =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_caps);
- klass->fixate_caps =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_fixate_caps);
- klass->accept_caps =
- GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default);
- klass->query = GST_DEBUG_FUNCPTR (gst_base_transform_default_query);
- klass->decide_allocation =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_decide_allocation);
- klass->propose_allocation =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_propose_allocation);
- klass->transform_size =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_size);
- klass->transform_meta =
- GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_meta);
-
- klass->sink_event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
- klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);
- klass->prepare_output_buffer =
- GST_DEBUG_FUNCPTR (default_prepare_output_buffer);
- klass->copy_metadata = GST_DEBUG_FUNCPTR (default_copy_metadata);
- klass->submit_input_buffer = GST_DEBUG_FUNCPTR (default_submit_input_buffer);
- klass->generate_output = GST_DEBUG_FUNCPTR (default_generate_output);
-}
-
-static void
-gst_base_transform_init (GstBaseTransform * trans,
- GstBaseTransformClass * bclass)
-{
- GstPadTemplate *pad_template;
- GstBaseTransformPrivate *priv;
-
- GST_DEBUG ("gst_base_transform_init");
-
- priv = trans->priv = gst_base_transform_get_instance_private (trans);
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
- g_return_if_fail (pad_template != NULL);
- trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
- gst_pad_set_event_function (trans->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
- gst_pad_set_chain_function (trans->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_chain));
- gst_pad_set_activatemode_function (trans->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_mode));
- gst_pad_set_query_function (trans->sinkpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_query));
- gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
-
- pad_template =
- gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
- g_return_if_fail (pad_template != NULL);
- trans->srcpad = gst_pad_new_from_template (pad_template, "src");
- gst_pad_set_event_function (trans->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
- gst_pad_set_getrange_function (trans->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
- gst_pad_set_activatemode_function (trans->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_mode));
- gst_pad_set_query_function (trans->srcpad,
- GST_DEBUG_FUNCPTR (gst_base_transform_query));
- gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
-
- priv->qos_enabled = DEFAULT_PROP_QOS;
- priv->cache_caps1 = NULL;
- priv->cache_caps2 = NULL;
- priv->pad_mode = GST_PAD_MODE_NONE;
- priv->gap_aware = FALSE;
- priv->prefer_passthrough = TRUE;
-
- priv->passthrough = FALSE;
- if (bclass->transform == NULL) {
- /* If no transform function, always_in_place is TRUE */
- GST_DEBUG_OBJECT (trans, "setting in_place TRUE");
- priv->always_in_place = TRUE;
-
- if (bclass->transform_ip == NULL) {
- GST_DEBUG_OBJECT (trans, "setting passthrough TRUE");
- priv->passthrough = TRUE;
- }
- }
-
- priv->processed = 0;
- priv->dropped = 0;
-}
-
-static GstCaps *
-gst_base_transform_default_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps, GstCaps * filter)
-{
- GstCaps *ret;
-
- GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps);
- /* no transform function, use the identity transform */
- if (filter) {
- ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
- } else {
- ret = gst_caps_ref (caps);
- }
- return ret;
-}
-
-/* given @caps on the src or sink pad (given by @direction)
- * calculate the possible caps on the other pad.
- *
- * Returns new caps, unref after usage.
- */
-static GstCaps *
-gst_base_transform_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps, GstCaps * filter)
-{
- GstCaps *ret = NULL;
- GstBaseTransformClass *klass;
-
- if (caps == NULL)
- return NULL;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- /* if there is a custom transform function, use this */
- if (klass->transform_caps) {
- GST_DEBUG_OBJECT (trans, "transform caps (direction = %d)", direction);
-
- GST_LOG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
- ret = klass->transform_caps (trans, direction, caps, filter);
- GST_LOG_OBJECT (trans, " to: %" GST_PTR_FORMAT, ret);
-
-#ifdef GST_ENABLE_EXTRA_CHECKS
- if (filter) {
- if (!gst_caps_is_subset (ret, filter)) {
- GstCaps *intersection;
-
- GST_ERROR_OBJECT (trans,
- "transform_caps returned caps %" GST_PTR_FORMAT
- " which are not a real subset of the filter caps %"
- GST_PTR_FORMAT, ret, filter);
- g_warning ("%s: transform_caps returned caps which are not a real "
- "subset of the filter caps", GST_ELEMENT_NAME (trans));
-
- intersection =
- gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (ret);
- ret = intersection;
- }
- }
-#endif
- }
-
- GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
-
- return ret;
-}
-
-static gboolean
-gst_base_transform_default_transform_meta (GstBaseTransform * trans,
- GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf)
-{
- const GstMetaInfo *info = meta->info;
- const gchar *const *tags;
-
- tags = gst_meta_api_type_get_tags (info->api);
-
- if (!tags)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-gst_base_transform_default_transform_size (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps, gsize size,
- GstCaps * othercaps, gsize * othersize)
-{
- gsize inunitsize, outunitsize, units;
- GstBaseTransformClass *klass;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (klass->get_unit_size == NULL) {
- /* if there is no transform_size and no unit_size, it means the
- * element does not modify the size of a buffer */
- *othersize = size;
- } else {
- /* there is no transform_size function, we have to use the unit_size
- * functions. This method assumes there is a fixed unit_size associated with
- * each caps. We provide the same amount of units on both sides. */
- if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))
- goto no_in_size;
-
- GST_DEBUG_OBJECT (trans,
- "input size %" G_GSIZE_FORMAT ", input unit size %" G_GSIZE_FORMAT,
- size, inunitsize);
-
- /* input size must be a multiple of the unit_size of the input caps */
- if (inunitsize == 0 || (size % inunitsize != 0))
- goto no_multiple;
-
- /* get the amount of units */
- units = size / inunitsize;
-
- /* now get the unit size of the output */
- if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize))
- goto no_out_size;
-
- /* the output size is the unit_size times the amount of units on the
- * input */
- *othersize = units * outunitsize;
- GST_DEBUG_OBJECT (trans, "transformed size to %" G_GSIZE_FORMAT,
- *othersize);
- }
- return TRUE;
-
- /* ERRORS */
-no_in_size:
- {
- GST_DEBUG_OBJECT (trans, "could not get in_size");
- g_warning ("%s: could not get in_size", GST_ELEMENT_NAME (trans));
- return FALSE;
- }
-no_multiple:
- {
- GST_DEBUG_OBJECT (trans, "Size %" G_GSIZE_FORMAT " is not a multiple of"
- "unit size %" G_GSIZE_FORMAT, size, inunitsize);
- g_warning ("%s: size %" G_GSIZE_FORMAT " is not a multiple of unit size %"
- G_GSIZE_FORMAT, GST_ELEMENT_NAME (trans), size, inunitsize);
- return FALSE;
- }
-no_out_size:
- {
- GST_DEBUG_OBJECT (trans, "could not get out_size");
- g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans));
- return FALSE;
- }
-}
-
-/* transform a buffer of @size with @caps on the pad with @direction to
- * the size of a buffer with @othercaps and store the result in @othersize
- *
- * We have two ways of doing this:
- * 1) use a custom transform size function, this is for complicated custom
- * cases with no fixed unit_size.
- * 2) use the unit_size functions where there is a relationship between the
- * caps and the size of a buffer.
- */
-static gboolean
-gst_base_transform_transform_size (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps,
- gsize size, GstCaps * othercaps, gsize * othersize)
-{
- GstBaseTransformClass *klass;
- gboolean ret = FALSE;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- GST_DEBUG_OBJECT (trans,
- "asked to transform size %" G_GSIZE_FORMAT " for caps %"
- GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
- size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
-
- if (klass->transform_size) {
- /* if there is a custom transform function, use this */
- ret = klass->transform_size (trans, direction, caps, size, othercaps,
- othersize);
- }
- return ret;
-}
-
-/* get the caps that can be handled by @pad. We perform:
- *
- * - take the caps of peer of otherpad,
- * - filter against the padtemplate of otherpad,
- * - calculate all transforms of remaining caps
- * - filter against template of @pad
- *
- * If there is no peer, we simply return the caps of the padtemplate of pad.
- */
-static GstCaps *
-gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
- GstCaps * filter)
-{
- GstPad *otherpad;
- GstCaps *peercaps = NULL, *caps, *temp, *peerfilter = NULL;
- GstCaps *templ, *otempl;
-
- otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
-
- templ = gst_pad_get_pad_template_caps (pad);
- otempl = gst_pad_get_pad_template_caps (otherpad);
-
- /* first prepare the filter to be sent onwards. We need to filter and
- * transform it to valid caps for the otherpad. */
- if (filter) {
- GST_DEBUG_OBJECT (pad, "filter caps %" GST_PTR_FORMAT, filter);
-
- /* filtered against our padtemplate of this pad */
- GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
- temp = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
-
- /* then see what we can transform this to */
- peerfilter = gst_base_transform_transform_caps (trans,
- GST_PAD_DIRECTION (pad), temp, NULL);
- GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, peerfilter);
- gst_caps_unref (temp);
-
- if (peerfilter) {
- if (!gst_caps_is_empty (peerfilter)) {
- /* and filter against the template of the other pad */
- GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, otempl);
- /* We keep the caps sorted like the returned caps */
- temp =
- gst_caps_intersect_full (peerfilter, otempl,
- GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
- gst_caps_unref (peerfilter);
- peerfilter = temp;
- }
-
- /* If we filter out everything, bail out */
- if (peerfilter && gst_caps_is_empty (peerfilter)) {
- GST_DEBUG_OBJECT (pad, "peer filter caps are empty");
- caps = peerfilter;
- peerfilter = NULL;
- goto done;
- }
- }
- }
-
- GST_DEBUG_OBJECT (pad, "peer filter caps %" GST_PTR_FORMAT, peerfilter);
-
- /* query the peer with the transformed filter */
- peercaps = gst_pad_peer_query_caps (otherpad, peerfilter);
-
- if (peerfilter)
- gst_caps_unref (peerfilter);
-
- if (peercaps) {
- GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peercaps);
-
- /* filtered against our padtemplate on the other side */
- GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, otempl);
- temp = gst_caps_intersect_full (peercaps, otempl, GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
- } else {
- temp = gst_caps_ref (otempl);
- }
-
- /* then see what we can transform this to */
- caps = gst_base_transform_transform_caps (trans,
- GST_PAD_DIRECTION (otherpad), temp, filter);
- GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps);
- gst_caps_unref (temp);
- if (caps == NULL || gst_caps_is_empty (caps))
- goto done;
-
- if (peercaps) {
- /* and filter against the template of this pad */
- GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
- /* We keep the caps sorted like the returned caps */
- temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
- gst_caps_unref (caps);
- caps = temp;
-
- if (trans->priv->prefer_passthrough) {
- /* Now try if we can put the untransformed downstream caps first */
- temp = gst_caps_intersect_full (peercaps, caps, GST_CAPS_INTERSECT_FIRST);
- if (!gst_caps_is_empty (temp)) {
- caps = gst_caps_merge (temp, caps);
- } else {
- gst_caps_unref (temp);
- }
- }
- } else {
- gst_caps_unref (caps);
- /* no peer or the peer can do anything, our padtemplate is enough then */
- if (filter) {
- caps = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST);
- } else {
- caps = gst_caps_ref (templ);
- }
- }
-
-done:
- GST_DEBUG_OBJECT (trans, "returning %" GST_PTR_FORMAT, caps);
-
- if (peercaps)
- gst_caps_unref (peercaps);
-
- gst_caps_unref (templ);
- gst_caps_unref (otempl);
-
- return caps;
-}
-
-/* takes ownership of the pool, allocator and query */
-static gboolean
-gst_base_transform_set_allocation (GstBaseTransform * trans,
- GstBufferPool * pool, GstAllocator * allocator,
- const GstAllocationParams * params, GstQuery * query)
-{
- GstAllocator *oldalloc;
- GstBufferPool *oldpool;
- GstQuery *oldquery;
- GstBaseTransformPrivate *priv = trans->priv;
-
- GST_OBJECT_LOCK (trans);
- oldpool = priv->pool;
- priv->pool = pool;
- priv->pool_active = FALSE;
-
- oldalloc = priv->allocator;
- priv->allocator = allocator;
-
- oldquery = priv->query;
- priv->query = query;
-
- if (params)
- priv->params = *params;
- else
- gst_allocation_params_init (&priv->params);
- GST_OBJECT_UNLOCK (trans);
-
- if (oldpool) {
- GST_DEBUG_OBJECT (trans, "deactivating old pool %p", oldpool);
- gst_buffer_pool_set_active (oldpool, FALSE);
- gst_object_unref (oldpool);
- }
- if (oldalloc) {
- gst_object_unref (oldalloc);
- }
- if (oldquery) {
- gst_query_unref (oldquery);
- }
- return TRUE;
-}
-
-static gboolean
-gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
- GstQuery * query)
-{
- guint i, n_metas;
- GstBaseTransformClass *klass;
- GstCaps *outcaps;
- GstBufferPool *pool;
- guint size, min, max;
- GstAllocator *allocator;
- GstAllocationParams params;
- GstStructure *config;
- gboolean update_allocator;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- n_metas = gst_query_get_n_allocation_metas (query);
- for (i = 0; i < n_metas; i++) {
- GType api;
- const GstStructure *params;
- gboolean remove;
-
- api = gst_query_parse_nth_allocation_meta (query, i, &params);
-
- /* by default we remove all metadata, subclasses should implement a
- * filter_meta function */
- if (gst_meta_api_type_has_tag (api, _gst_meta_tag_memory)) {
- /* remove all memory dependent metadata because we are going to have to
- * allocate different memory for input and output. */
- GST_LOG_OBJECT (trans, "removing memory specific metadata %s",
- g_type_name (api));
- remove = TRUE;
- } else if (G_LIKELY (klass->filter_meta)) {
- /* remove if the subclass said so */
- remove = !klass->filter_meta (trans, query, api, params);
- GST_LOG_OBJECT (trans, "filter_meta for api %s returned: %s",
- g_type_name (api), (remove ? "remove" : "keep"));
- } else {
- GST_LOG_OBJECT (trans, "removing metadata %s", g_type_name (api));
- remove = TRUE;
- }
-
- if (remove) {
- gst_query_remove_nth_allocation_meta (query, i);
- i--;
- n_metas--;
- }
- }
-
- gst_query_parse_allocation (query, &outcaps, NULL);
-
- /* we got configuration from our peer or the decide_allocation method,
- * parse them */
- if (gst_query_get_n_allocation_params (query) > 0) {
- /* try the allocator */
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- update_allocator = TRUE;
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- update_allocator = FALSE;
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0) {
- gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
-
- if (pool == NULL) {
- /* no pool, we can make our own */
- GST_DEBUG_OBJECT (trans, "no pool, making new pool");
- pool = gst_buffer_pool_new ();
- }
- } else {
- pool = NULL;
- size = min = max = 0;
- }
-
- /* now configure */
- if (pool) {
- config = gst_buffer_pool_get_config (pool);
- gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
- gst_buffer_pool_config_set_allocator (config, allocator, &params);
-
- /* buffer pool may have to do some changes */
- if (!gst_buffer_pool_set_config (pool, config)) {
- config = gst_buffer_pool_get_config (pool);
-
- /* If change are not acceptable, fallback to generic pool */
- if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
- max)) {
- GST_DEBUG_OBJECT (trans, "unsupported pool, making new pool");
-
- gst_object_unref (pool);
- pool = gst_buffer_pool_new ();
- gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
- gst_buffer_pool_config_set_allocator (config, allocator, &params);
- }
-
- if (!gst_buffer_pool_set_config (pool, config))
- goto config_failed;
- }
- }
-
- if (update_allocator)
- gst_query_set_nth_allocation_param (query, 0, allocator, &params);
- else
- gst_query_add_allocation_param (query, allocator, &params);
- if (allocator)
- gst_object_unref (allocator);
-
- if (pool) {
- gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
- gst_object_unref (pool);
- }
-
- return TRUE;
-
-config_failed:
- if (pool)
- gst_object_unref (pool);
-
- GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS,
- ("Failed to configure the buffer pool"),
- ("Configuration is most likely invalid, please report this issue."));
- return FALSE;
-}
-
-static gboolean
-gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps)
-{
- GstQuery *query;
- gboolean result = TRUE;
- GstBufferPool *pool = NULL;
- GstBaseTransformClass *klass;
- GstBaseTransformPrivate *priv = trans->priv;
- GstAllocator *allocator;
- GstAllocationParams params;
-
- /* there are these possibilities:
- *
- * 1) we negotiated passthrough, we can proxy the bufferpool directly and we
- * will do that whenever some upstream does an allocation query.
- * 2) we need to do a transform, we need to get a bufferpool from downstream
- * and configure it. When upstream does the ALLOCATION query, the
- * propose_allocation vmethod will be called and we will configure the
- * upstream allocator with our proposed values then.
- */
- if (priv->passthrough || priv->always_in_place) {
- /* we are in passthrough, the input buffer is never copied and always passed
- * along. We never allocate an output buffer on the srcpad. What we do is
- * let the upstream element decide if it wants to use a bufferpool and
- * then we will proxy the downstream pool */
- GST_DEBUG_OBJECT (trans, "we're passthough, delay bufferpool");
- gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL);
- return TRUE;
- }
-
- /* not passthrough, we need to allocate */
- /* find a pool for the negotiated caps now */
- GST_DEBUG_OBJECT (trans, "doing allocation query");
- query = gst_query_new_allocation (outcaps, TRUE);
- if (!gst_pad_peer_query (trans->srcpad, query)) {
- /* not a problem, just debug a little */
- GST_DEBUG_OBJECT (trans, "peer ALLOCATION query failed");
- }
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- GST_DEBUG_OBJECT (trans, "calling decide_allocation");
- g_assert (klass->decide_allocation != NULL);
- result = klass->decide_allocation (trans, query);
-
- GST_DEBUG_OBJECT (trans, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
- query);
-
- if (!result)
- goto no_decide_allocation;
-
- /* check again in case the sub-class have switch to passthrough/in-place
- * after looking at the meta APIs */
- if (priv->passthrough || priv->always_in_place) {
- GST_DEBUG_OBJECT (trans, "no doing passthrough, delay bufferpool");
- gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL);
- gst_query_unref (query);
- return TRUE;
- }
-
- /* we got configuration from our peer or the decide_allocation method,
- * parse them */
- if (gst_query_get_n_allocation_params (query) > 0) {
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0)
- gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
-
- /* now store */
- result =
- gst_base_transform_set_allocation (trans, pool, allocator, &params,
- query);
-
- return result;
-
- /* Errors */
-no_decide_allocation:
- {
- GST_WARNING_OBJECT (trans, "Subclass failed to decide allocation");
- gst_query_unref (query);
-
- return result;
- }
-}
-
-/* function triggered when the in and out caps are negotiated and need
- * to be configured in the subclass. */
-static gboolean
-gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,
- GstCaps * out)
-{
- gboolean ret = TRUE;
- GstBaseTransformClass *klass;
- GstBaseTransformPrivate *priv = trans->priv;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- GST_DEBUG_OBJECT (trans, "in caps: %" GST_PTR_FORMAT, in);
- GST_DEBUG_OBJECT (trans, "out caps: %" GST_PTR_FORMAT, out);
-
- /* clear the cache */
- gst_caps_replace (&priv->cache_caps1, NULL);
- gst_caps_replace (&priv->cache_caps2, NULL);
-
- /* figure out same caps state */
- priv->have_same_caps = gst_caps_is_equal (in, out);
- GST_DEBUG_OBJECT (trans, "have_same_caps: %d", priv->have_same_caps);
-
- /* Set the passthrough if the class wants passthrough_on_same_caps
- * and we have the same caps on each pad */
- if (klass->passthrough_on_same_caps)
- gst_base_transform_set_passthrough (trans, priv->have_same_caps);
-
- /* now configure the element with the caps */
- if (klass->set_caps) {
- GST_DEBUG_OBJECT (trans, "Calling set_caps method to setup caps");
- ret = klass->set_caps (trans, in, out);
- }
-
- return ret;
-}
-
-static GstCaps *
-gst_base_transform_default_fixate_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
-{
- othercaps = gst_caps_fixate (othercaps);
- GST_DEBUG_OBJECT (trans, "fixated to %" GST_PTR_FORMAT, othercaps);
-
- return othercaps;
-}
-
-/* given a fixed @caps on @pad, create the best possible caps for the
- * other pad.
- * @caps must be fixed when calling this function.
- *
- * This function calls the transform caps vmethod of the basetransform to figure
- * out the possible target formats. It then tries to select the best format from
- * this list by:
- *
- * - attempt passthrough if the target caps is a superset of the input caps
- * - fixating by using peer caps
- * - fixating with transform fixate function
- * - fixating with pad fixate functions.
- *
- * this function returns a caps that can be transformed into and is accepted by
- * the peer element.
- */
-static GstCaps *
-gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
- GstCaps * caps)
-{
- GstBaseTransformClass *klass;
- GstPad *otherpad, *otherpeer;
- GstCaps *othercaps;
- gboolean is_fixed;
-
- /* caps must be fixed here, this is a programming error if it's not */
- g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
- otherpeer = gst_pad_get_peer (otherpad);
-
- /* see how we can transform the input caps. We need to do this even for
- * passthrough because it might be possible that this element cannot support
- * passthrough at all. */
- othercaps = gst_base_transform_transform_caps (trans,
- GST_PAD_DIRECTION (pad), caps, NULL);
-
- /* The caps we can actually output is the intersection of the transformed
- * caps with the pad template for the pad */
- if (othercaps && !gst_caps_is_empty (othercaps)) {
- GstCaps *intersect, *templ_caps;
-
- templ_caps = gst_pad_get_pad_template_caps (otherpad);
- GST_DEBUG_OBJECT (trans,
- "intersecting against padtemplate %" GST_PTR_FORMAT, templ_caps);
-
- intersect =
- gst_caps_intersect_full (othercaps, templ_caps,
- GST_CAPS_INTERSECT_FIRST);
-
- gst_caps_unref (othercaps);
- gst_caps_unref (templ_caps);
- othercaps = intersect;
- }
-
- /* check if transform is empty */
- if (!othercaps || gst_caps_is_empty (othercaps))
- goto no_transform;
-
- /* if the othercaps are not fixed, we need to fixate them, first attempt
- * is by attempting passthrough if the othercaps are a superset of caps. */
- /* FIXME. maybe the caps is not fixed because it has multiple structures of
- * fixed caps */
- is_fixed = gst_caps_is_fixed (othercaps);
- if (!is_fixed) {
- GST_DEBUG_OBJECT (trans,
- "transform returned non fixed %" GST_PTR_FORMAT, othercaps);
-
- /* Now let's see what the peer suggests based on our transformed caps */
- if (otherpeer) {
- GstCaps *peercaps, *intersection, *templ_caps;
-
- GST_DEBUG_OBJECT (trans,
- "Checking peer caps with filter %" GST_PTR_FORMAT, othercaps);
-
- peercaps = gst_pad_query_caps (otherpeer, othercaps);
- GST_DEBUG_OBJECT (trans, "Resulted in %" GST_PTR_FORMAT, peercaps);
- if (!gst_caps_is_empty (peercaps)) {
- templ_caps = gst_pad_get_pad_template_caps (otherpad);
-
- GST_DEBUG_OBJECT (trans,
- "Intersecting with template caps %" GST_PTR_FORMAT, templ_caps);
-
- intersection =
- gst_caps_intersect_full (peercaps, templ_caps,
- GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
- intersection);
- gst_caps_unref (peercaps);
- gst_caps_unref (templ_caps);
- peercaps = intersection;
-
- GST_DEBUG_OBJECT (trans,
- "Intersecting with transformed caps %" GST_PTR_FORMAT, othercaps);
- intersection =
- gst_caps_intersect_full (peercaps, othercaps,
- GST_CAPS_INTERSECT_FIRST);
- GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
- intersection);
- gst_caps_unref (peercaps);
- gst_caps_unref (othercaps);
- othercaps = intersection;
- } else {
- gst_caps_unref (othercaps);
- othercaps = peercaps;
- }
-
- is_fixed = gst_caps_is_fixed (othercaps);
- } else {
- GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
- gst_caps_unref (othercaps);
- othercaps = gst_caps_ref (caps);
- is_fixed = TRUE;
- }
- }
- if (gst_caps_is_empty (othercaps))
- goto no_transform_possible;
-
- GST_DEBUG ("have %sfixed caps %" GST_PTR_FORMAT, (is_fixed ? "" : "non-"),
- othercaps);
-
- /* second attempt at fixation, call the fixate vmethod */
- /* caps could be fixed but the subclass may want to add fields */
- if (klass->fixate_caps) {
- GST_DEBUG_OBJECT (trans, "calling fixate_caps for %" GST_PTR_FORMAT
- " using caps %" GST_PTR_FORMAT " on pad %s:%s", othercaps, caps,
- GST_DEBUG_PAD_NAME (otherpad));
- /* note that we pass the complete array of structures to the fixate
- * function, it needs to truncate itself */
- othercaps =
- klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
-
- if (!othercaps) {
- g_critical ("basetransform: second attempt to fixate caps returned "
- "invalid (NULL) caps on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- }
- is_fixed = othercaps && gst_caps_is_fixed (othercaps);
- GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
- }
-
- /* caps should be fixed now, if not we have to fail. */
- if (!is_fixed)
- goto could_not_fixate;
-
- /* and peer should accept */
- if (otherpeer && !gst_pad_query_accept_caps (otherpeer, othercaps))
- goto peer_no_accept;
-
- GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
- ", and got final caps %" GST_PTR_FORMAT, caps, othercaps);
-
- if (otherpeer)
- gst_object_unref (otherpeer);
-
- return othercaps;
-
- /* ERRORS */
-no_transform:
- {
- GST_DEBUG_OBJECT (trans,
- "transform returned useless %" GST_PTR_FORMAT, othercaps);
- goto error_cleanup;
- }
-no_transform_possible:
- {
- GST_DEBUG_OBJECT (trans,
- "transform could not transform %" GST_PTR_FORMAT
- " in anything we support", caps);
- goto error_cleanup;
- }
-could_not_fixate:
- {
- GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
- goto error_cleanup;
- }
-peer_no_accept:
- {
- GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT
- " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
- goto error_cleanup;
- }
-error_cleanup:
- {
- if (otherpeer)
- gst_object_unref (otherpeer);
- if (othercaps)
- gst_caps_unref (othercaps);
- return NULL;
- }
-}
-
-static gboolean
-gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps)
-{
- GstPad *pad, *otherpad;
- GstCaps *templ, *otempl, *ocaps = NULL;
- gboolean ret = TRUE;
-
- pad =
- (direction ==
- GST_PAD_SINK) ? GST_BASE_TRANSFORM_SINK_PAD (trans) :
- GST_BASE_TRANSFORM_SRC_PAD (trans);
- otherpad =
- (direction ==
- GST_PAD_SINK) ? GST_BASE_TRANSFORM_SRC_PAD (trans) :
- GST_BASE_TRANSFORM_SINK_PAD (trans);
-
- GST_DEBUG_OBJECT (trans, "accept caps %" GST_PTR_FORMAT, caps);
-
- templ = gst_pad_get_pad_template_caps (pad);
- otempl = gst_pad_get_pad_template_caps (otherpad);
-
- /* get all the formats we can handle on this pad */
- GST_DEBUG_OBJECT (trans, "intersect with pad template: %" GST_PTR_FORMAT,
- templ);
- if (!gst_caps_can_intersect (caps, templ))
- goto reject_caps;
-
- GST_DEBUG_OBJECT (trans, "trying to transform with filter: %"
- GST_PTR_FORMAT " (the other pad template)", otempl);
- ocaps = gst_base_transform_transform_caps (trans, direction, caps, otempl);
- if (!ocaps || gst_caps_is_empty (ocaps))
- goto no_transform_possible;
-
-done:
- GST_DEBUG_OBJECT (trans, "accept-caps result: %d", ret);
- if (ocaps)
- gst_caps_unref (ocaps);
- gst_caps_unref (templ);
- gst_caps_unref (otempl);
- return ret;
-
- /* ERRORS */
-reject_caps:
- {
- GST_DEBUG_OBJECT (trans, "caps can't intersect with the template");
- ret = FALSE;
- goto done;
- }
-no_transform_possible:
- {
- GST_DEBUG_OBJECT (trans,
- "transform could not transform %" GST_PTR_FORMAT
- " in anything we support", caps);
- ret = FALSE;
- goto done;
- }
-}
-
-/* called when new caps arrive on the sink pad,
- * We try to find the best caps for the other side using our _find_transform()
- * function. If there are caps, we configure the transform for this new
- * transformation.
- */
-static gboolean
-gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad,
- GstCaps * incaps)
-{
- GstBaseTransformPrivate *priv = trans->priv;
- GstCaps *outcaps, *prev_incaps = NULL, *prev_outcaps = NULL;
- gboolean ret = TRUE;
-
- GST_DEBUG_OBJECT (pad, "have new caps %p %" GST_PTR_FORMAT, incaps, incaps);
-
- /* find best possible caps for the other pad */
- outcaps = gst_base_transform_find_transform (trans, pad, incaps);
- if (!outcaps || gst_caps_is_empty (outcaps))
- goto no_transform_possible;
-
- /* configure the element now */
-
- /* if we have the same caps, we can optimize and reuse the input caps */
- if (gst_caps_is_equal (incaps, outcaps)) {
- GST_INFO_OBJECT (trans, "reuse caps");
- gst_caps_unref (outcaps);
- outcaps = gst_caps_ref (incaps);
- }
-
- prev_incaps = gst_pad_get_current_caps (trans->sinkpad);
- prev_outcaps = gst_pad_get_current_caps (trans->srcpad);
- if (prev_incaps && prev_outcaps && gst_caps_is_equal (prev_incaps, incaps)
- && gst_caps_is_equal (prev_outcaps, outcaps)) {
- GST_DEBUG_OBJECT (trans,
- "New caps equal to old ones: %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT,
- incaps, outcaps);
- ret = TRUE;
- } else {
- /* call configure now */
- if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
- goto failed_configure;
-
- if (!prev_outcaps || !gst_caps_is_equal (outcaps, prev_outcaps))
- /* let downstream know about our caps */
- ret = gst_pad_set_caps (trans->srcpad, outcaps);
- }
-
- if (ret) {
- /* try to get a pool when needed */
- ret = gst_base_transform_do_bufferpool (trans, outcaps);
- }
-
-done:
- if (outcaps)
- gst_caps_unref (outcaps);
- if (prev_incaps)
- gst_caps_unref (prev_incaps);
- if (prev_outcaps)
- gst_caps_unref (prev_outcaps);
-
- GST_OBJECT_LOCK (trans);
- priv->negotiated = ret;
- GST_OBJECT_UNLOCK (trans);
-
- return ret;
-
- /* ERRORS */
-no_transform_possible:
- {
- GST_WARNING_OBJECT (trans,
- "transform could not transform %" GST_PTR_FORMAT
- " in anything we support", incaps);
- ret = FALSE;
- goto done;
- }
-failed_configure:
- {
- GST_WARNING_OBJECT (trans, "FAILED to configure incaps %" GST_PTR_FORMAT
- " and outcaps %" GST_PTR_FORMAT, incaps, outcaps);
- ret = FALSE;
- goto done;
- }
-}
-
-static gboolean
-gst_base_transform_default_propose_allocation (GstBaseTransform * trans,
- GstQuery * decide_query, GstQuery * query)
-{
- gboolean ret;
-
- if (decide_query == NULL) {
- GST_DEBUG_OBJECT (trans, "doing passthrough query");
- ret = gst_pad_peer_query (trans->srcpad, query);
- } else {
- guint i, n_metas;
- /* non-passthrough, copy all metadata, decide_query does not contain the
- * metadata anymore that depends on the buffer memory */
- n_metas = gst_query_get_n_allocation_metas (decide_query);
- for (i = 0; i < n_metas; i++) {
- GType api;
- const GstStructure *params;
-
- api = gst_query_parse_nth_allocation_meta (decide_query, i, &params);
- GST_DEBUG_OBJECT (trans, "proposing metadata %s", g_type_name (api));
- gst_query_add_allocation_meta (query, api, params);
- }
- ret = TRUE;
- }
- return ret;
-}
-
-static gboolean
-gst_base_transform_reconfigure_unlocked (GstBaseTransform * trans)
-{
- gboolean reconfigure, ret = TRUE;
-
- reconfigure = gst_pad_check_reconfigure (trans->srcpad);
-
- if (G_UNLIKELY (reconfigure)) {
- GstCaps *incaps;
-
- GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
-
- incaps = gst_pad_get_current_caps (trans->sinkpad);
- if (incaps == NULL)
- goto done;
-
- /* if we need to reconfigure we pretend new caps arrived. This
- * will reconfigure the transform with the new output format. */
- if (!gst_base_transform_setcaps (trans, trans->sinkpad, incaps)) {
- GST_ELEMENT_WARNING (trans, STREAM, FORMAT,
- ("not negotiated"), ("not negotiated"));
- ret = FALSE;
- }
-
- gst_caps_unref (incaps);
- }
-
-done:
-
- if (!ret)
- gst_pad_mark_reconfigure (trans->srcpad);
-
- return ret;
-}
-
-/**
- * gst_base_transform_reconfigure:
- * @trans: the #GstBaseTransform to set
- *
- * Negotiates src pad caps with downstream elements if the source pad is
- * marked as needing reconfiguring. Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in
- * any case. But marks it again if negotiation fails.
- *
- * Do not call this in the #GstBaseTransformClass::transform or
- * #GstBaseTransformClass::transform_ip vmethod. Call this in
- * #GstBaseTransformClass::submit_input_buffer,
- * #GstBaseTransformClass::prepare_output_buffer or in
- * #GstBaseTransformClass::generate_output _before_ any output buffer is
- * allocated.
- *
- * It will be default be called when handling an ALLOCATION query or at the
- * very beginning of the default #GstBaseTransformClass::submit_input_buffer
- * implementation.
- *
- * Returns: %TRUE if the negotiation succeeded, else %FALSE.
- *
- * Since: 1.18
- */
-gboolean
-gst_base_transform_reconfigure (GstBaseTransform * trans)
-{
- gboolean ret;
-
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
-
- GST_PAD_STREAM_LOCK (trans->sinkpad);
- ret = gst_base_transform_reconfigure_unlocked (trans);
- if (!ret)
- gst_pad_mark_reconfigure (trans->srcpad);
- GST_PAD_STREAM_UNLOCK (trans->sinkpad);
-
- return ret;
-}
-
-static gboolean
-gst_base_transform_default_query (GstBaseTransform * trans,
- GstPadDirection direction, GstQuery * query)
-{
- gboolean ret = FALSE;
- GstPad *pad, *otherpad;
- GstBaseTransformClass *klass;
- GstBaseTransformPrivate *priv = trans->priv;
-
- if (direction == GST_PAD_SRC) {
- pad = trans->srcpad;
- otherpad = trans->sinkpad;
- } else {
- pad = trans->sinkpad;
- otherpad = trans->srcpad;
- }
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_ALLOCATION:
- {
- GstQuery *decide_query = NULL;
-
- /* can only be done on the sinkpad */
- if (direction != GST_PAD_SINK)
- goto done;
-
- ret = gst_base_transform_reconfigure_unlocked (trans);
- if (G_UNLIKELY (!ret))
- goto done;
-
- GST_OBJECT_LOCK (trans);
- if (!priv->negotiated && !priv->passthrough && (klass->set_caps != NULL)) {
- GST_DEBUG_OBJECT (trans,
- "not negotiated yet but need negotiation, can't answer ALLOCATION query");
- GST_OBJECT_UNLOCK (trans);
- goto done;
- }
-
- decide_query = trans->priv->query;
- trans->priv->query = NULL;
- GST_OBJECT_UNLOCK (trans);
-
- GST_DEBUG_OBJECT (trans,
- "calling propose allocation with query %" GST_PTR_FORMAT,
- decide_query);
-
- /* pass the query to the propose_allocation vmethod if any */
- if (G_LIKELY (klass->propose_allocation))
- ret = klass->propose_allocation (trans, decide_query, query);
- else
- ret = FALSE;
-
- if (decide_query) {
- GST_OBJECT_LOCK (trans);
-
- if (trans->priv->query == NULL)
- trans->priv->query = decide_query;
- else
- gst_query_unref (decide_query);
-
- GST_OBJECT_UNLOCK (trans);
- }
-
- GST_DEBUG_OBJECT (trans, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret,
- query);
- break;
- }
- case GST_QUERY_POSITION:
- {
- GstFormat format;
-
- gst_query_parse_position (query, &format, NULL);
- if (format == GST_FORMAT_TIME && trans->segment.format == GST_FORMAT_TIME) {
- gint64 pos;
- ret = TRUE;
-
- if ((direction == GST_PAD_SINK)
- || (trans->priv->position_out == GST_CLOCK_TIME_NONE)) {
- pos =
- gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
- trans->segment.position);
- } else {
- pos = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
- trans->priv->position_out);
- }
- gst_query_set_position (query, format, pos);
- } else {
- ret = gst_pad_peer_query (otherpad, query);
- }
- break;
- }
- case GST_QUERY_ACCEPT_CAPS:
- {
- GstCaps *caps;
-
- gst_query_parse_accept_caps (query, &caps);
- if (klass->accept_caps) {
- ret = klass->accept_caps (trans, direction, caps);
- gst_query_set_accept_caps_result (query, ret);
- /* return TRUE, we answered the query */
- ret = TRUE;
- }
- break;
- }
- case GST_QUERY_CAPS:
- {
- GstCaps *filter, *caps;
-
- gst_query_parse_caps (query, &filter);
- caps = gst_base_transform_query_caps (trans, pad, filter);
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- ret = TRUE;
- break;
- }
- default:
- ret = gst_pad_peer_query (otherpad, query);
- break;
- }
-
-done:
- return ret;
-}
-
-static gboolean
-gst_base_transform_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstBaseTransform *trans;
- GstBaseTransformClass *bclass;
- gboolean ret = FALSE;
-
- trans = GST_BASE_TRANSFORM_CAST (parent);
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (bclass->query)
- ret = bclass->query (trans, GST_PAD_DIRECTION (pad), query);
-
- return ret;
-}
-
-/* this function either returns the input buffer without incrementing the
- * refcount or it allocates a new (writable) buffer */
-static GstFlowReturn
-default_prepare_output_buffer (GstBaseTransform * trans,
- GstBuffer * inbuf, GstBuffer ** outbuf)
-{
- GstBaseTransformPrivate *priv;
- GstFlowReturn ret;
- GstBaseTransformClass *bclass;
- GstCaps *incaps, *outcaps;
- gsize insize, outsize;
- gboolean res;
-
- priv = trans->priv;
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- /* figure out how to allocate an output buffer */
- if (priv->passthrough) {
- /* passthrough, we will not modify the incoming buffer so we can just
- * reuse it */
- GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer");
- *outbuf = inbuf;
- goto done;
- }
-
- /* we can't reuse the input buffer */
- if (priv->pool) {
- if (!priv->pool_active) {
- GST_DEBUG_OBJECT (trans, "setting pool %p active", priv->pool);
- if (!gst_buffer_pool_set_active (priv->pool, TRUE))
- goto activate_failed;
- priv->pool_active = TRUE;
- }
- GST_DEBUG_OBJECT (trans, "using pool alloc");
- ret = gst_buffer_pool_acquire_buffer (priv->pool, outbuf, NULL);
- if (ret != GST_FLOW_OK)
- goto alloc_failed;
-
- goto copy_meta;
- }
-
- /* no pool, we need to figure out the size of the output buffer first */
- if ((bclass->transform_ip != NULL) && priv->always_in_place) {
- /* we want to do an in-place alloc */
- if (gst_buffer_is_writable (inbuf)) {
- GST_DEBUG_OBJECT (trans, "inplace reuse writable input buffer");
- *outbuf = inbuf;
- } else {
- GST_DEBUG_OBJECT (trans, "making writable buffer copy");
- /* we make a copy of the input buffer */
- *outbuf = gst_buffer_copy (inbuf);
- }
- goto done;
- }
-
- /* else use the transform function to get the size */
- incaps = gst_pad_get_current_caps (trans->sinkpad);
- outcaps = gst_pad_get_current_caps (trans->srcpad);
-
- /* srcpad might be flushing already if we're being shut down */
- if (outcaps == NULL)
- goto no_outcaps;
-
- GST_DEBUG_OBJECT (trans, "getting output size for alloc");
- /* copy transform, figure out the output size */
- insize = gst_buffer_get_size (inbuf);
- res = gst_base_transform_transform_size (trans,
- GST_PAD_SINK, incaps, insize, outcaps, &outsize);
-
- gst_caps_unref (incaps);
- gst_caps_unref (outcaps);
-
- if (!res)
- goto unknown_size;
-
- GST_DEBUG_OBJECT (trans, "doing alloc of size %" G_GSIZE_FORMAT, outsize);
- *outbuf = gst_buffer_new_allocate (priv->allocator, outsize, &priv->params);
- if (!*outbuf) {
- ret = GST_FLOW_ERROR;
- goto alloc_failed;
- }
-
-copy_meta:
- /* copy the metadata */
- if (bclass->copy_metadata)
- if (!bclass->copy_metadata (trans, inbuf, *outbuf)) {
- /* something failed, post a warning */
- GST_ELEMENT_WARNING (trans, STREAM, NOT_IMPLEMENTED,
- ("could not copy metadata"), (NULL));
- }
-
-done:
- return GST_FLOW_OK;
-
- /* ERRORS */
-activate_failed:
- {
- GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS,
- ("failed to activate bufferpool"), ("failed to activate bufferpool"));
- return GST_FLOW_ERROR;
- }
-unknown_size:
- {
- GST_ERROR_OBJECT (trans, "unknown output size");
- return GST_FLOW_ERROR;
- }
-alloc_failed:
- {
- GST_DEBUG_OBJECT (trans, "could not allocate buffer from pool");
- return ret;
- }
-no_outcaps:
- {
- GST_DEBUG_OBJECT (trans, "no output caps, source pad has been deactivated");
- gst_caps_unref (incaps);
- return GST_FLOW_FLUSHING;
- }
-}
-
-typedef struct
-{
- GstBaseTransform *trans;
- GstBuffer *outbuf;
-} CopyMetaData;
-
-static gboolean
-foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
-{
- CopyMetaData *data = user_data;
- GstBaseTransform *trans = data->trans;
- GstBaseTransformClass *klass;
- const GstMetaInfo *info = (*meta)->info;
- GstBuffer *outbuf = data->outbuf;
- gboolean do_copy = FALSE;
-
- klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) {
- /* never call the transform_meta with memory specific metadata */
- GST_DEBUG_OBJECT (trans, "not copying memory specific metadata %s",
- g_type_name (info->api));
- do_copy = FALSE;
- } else if (klass->transform_meta) {
- do_copy = klass->transform_meta (trans, outbuf, *meta, inbuf);
- GST_DEBUG_OBJECT (trans, "transformed metadata %s: copy: %d",
- g_type_name (info->api), do_copy);
- }
-
- /* we only copy metadata when the subclass implemented a transform_meta
- * function and when it returns %TRUE */
- if (do_copy) {
- GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
- /* simply copy then */
- if (info->transform_func) {
- GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api));
- info->transform_func (outbuf, *meta, inbuf,
- _gst_meta_transform_copy, &copy_data);
- } else {
- GST_DEBUG_OBJECT (trans, "couldn't copy metadata %s",
- g_type_name (info->api));
- }
- }
- return TRUE;
-}
-
-static gboolean
-default_copy_metadata (GstBaseTransform * trans,
- GstBuffer * inbuf, GstBuffer * outbuf)
-{
- GstBaseTransformPrivate *priv = trans->priv;
- CopyMetaData data;
-
- /* now copy the metadata */
- GST_DEBUG_OBJECT (trans, "copying metadata");
-
- /* this should not happen, buffers allocated from a pool or with
- * new_allocate should always be writable. */
- if (!gst_buffer_is_writable (outbuf))
- goto not_writable;
-
- /* when we get here, the metadata should be writable */
- gst_buffer_copy_into (outbuf, inbuf,
- GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
-
- /* clear the GAP flag when the subclass does not understand it */
- if (!priv->gap_aware)
- GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
-
-
- data.trans = trans;
- data.outbuf = outbuf;
-
- gst_buffer_foreach_meta (inbuf, foreach_metadata, &data);
-
- return TRUE;
-
- /* ERRORS */
-not_writable:
- {
- GST_WARNING_OBJECT (trans, "buffer %p not writable", outbuf);
- return FALSE;
- }
-}
-
-/* Given @caps calculate the size of one unit.
- *
- * For video caps, this is the size of one frame (and thus one buffer).
- * For audio caps, this is the size of one sample.
- *
- * These values are cached since they do not change and the calculation
- * potentially involves parsing caps and other expensive stuff.
- *
- * We have two cache locations to store the size, one for the source caps
- * and one for the sink caps.
- *
- * this function returns %FALSE if no size could be calculated.
- */
-static gboolean
-gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
- gsize * size)
-{
- gboolean res = FALSE;
- GstBaseTransformClass *bclass;
- GstBaseTransformPrivate *priv = trans->priv;
-
- /* see if we have the result cached */
- if (priv->cache_caps1 == caps) {
- *size = priv->cache_caps1_size;
- GST_DEBUG_OBJECT (trans,
- "returned %" G_GSIZE_FORMAT " from first cache", *size);
- return TRUE;
- }
- if (priv->cache_caps2 == caps) {
- *size = priv->cache_caps2_size;
- GST_DEBUG_OBJECT (trans,
- "returned %" G_GSIZE_FORMAT " from second cached", *size);
- return TRUE;
- }
-
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
- res = bclass->get_unit_size (trans, caps, size);
- GST_DEBUG_OBJECT (trans,
- "caps %" GST_PTR_FORMAT " has unit size %" G_GSIZE_FORMAT ", res %s",
- caps, *size, res ? "TRUE" : "FALSE");
-
- if (res) {
- /* and cache the values */
- if (priv->cache_caps1 == NULL) {
- gst_caps_replace (&priv->cache_caps1, caps);
- priv->cache_caps1_size = *size;
- GST_DEBUG_OBJECT (trans,
- "caching %" G_GSIZE_FORMAT " in first cache", *size);
- } else if (priv->cache_caps2 == NULL) {
- gst_caps_replace (&priv->cache_caps2, caps);
- priv->cache_caps2_size = *size;
- GST_DEBUG_OBJECT (trans,
- "caching %" G_GSIZE_FORMAT " in second cache", *size);
- } else {
- GST_DEBUG_OBJECT (trans, "no free spot to cache unit_size");
- }
- }
- return res;
-}
-
-static gboolean
-gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event)
-{
- GstBaseTransform *trans;
- GstBaseTransformClass *bclass;
- gboolean ret = TRUE;
-
- trans = GST_BASE_TRANSFORM_CAST (parent);
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (bclass->sink_event)
- ret = bclass->sink_event (trans, event);
- else
- gst_event_unref (event);
-
- return ret;
-}
-
-static gboolean
-gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
-{
- gboolean ret = TRUE, forward = TRUE;
- GstBaseTransformPrivate *priv = trans->priv;
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- break;
- case GST_EVENT_FLUSH_STOP:
- GST_OBJECT_LOCK (trans);
- /* reset QoS parameters */
- priv->proportion = 1.0;
- priv->earliest_time = -1;
- priv->discont = FALSE;
- priv->processed = 0;
- priv->dropped = 0;
- GST_OBJECT_UNLOCK (trans);
- /* we need new segment info after the flush. */
- trans->have_segment = FALSE;
- gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
- priv->position_out = GST_CLOCK_TIME_NONE;
- break;
- case GST_EVENT_EOS:
- break;
- case GST_EVENT_TAG:
- break;
- case GST_EVENT_CAPS:
- {
- GstCaps *caps;
-
- gst_event_parse_caps (event, &caps);
- /* clear any pending reconfigure flag */
- gst_pad_check_reconfigure (trans->srcpad);
- ret = gst_base_transform_setcaps (trans, trans->sinkpad, caps);
- if (!ret)
- gst_pad_mark_reconfigure (trans->srcpad);
-
- forward = FALSE;
- break;
- }
- case GST_EVENT_SEGMENT:
- {
- gst_event_copy_segment (event, &trans->segment);
- trans->have_segment = TRUE;
-
- GST_DEBUG_OBJECT (trans, "received SEGMENT %" GST_SEGMENT_FORMAT,
- &trans->segment);
- break;
- }
- default:
- break;
- }
-
- if (ret && forward)
- ret = gst_pad_push_event (trans->srcpad, event);
- else
- gst_event_unref (event);
-
- return ret;
-}
-
-static gboolean
-gst_base_transform_src_event (GstPad * pad, GstObject * parent,
- GstEvent * event)
-{
- GstBaseTransform *trans;
- GstBaseTransformClass *bclass;
- gboolean ret = TRUE;
-
- trans = GST_BASE_TRANSFORM_CAST (parent);
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (bclass->src_event)
- ret = bclass->src_event (trans, event);
- else
- gst_event_unref (event);
-
- return ret;
-}
-
-static gboolean
-gst_base_transform_src_eventfunc (GstBaseTransform * trans, GstEvent * event)
-{
- gboolean ret;
-
- GST_DEBUG_OBJECT (trans, "handling event %p %" GST_PTR_FORMAT, event, event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- break;
- case GST_EVENT_NAVIGATION:
- break;
- case GST_EVENT_QOS:
- {
- gdouble proportion;
- GstClockTimeDiff diff;
- GstClockTime timestamp;
-
- gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
- gst_base_transform_update_qos (trans, proportion, diff, timestamp);
- break;
- }
- default:
- break;
- }
-
- ret = gst_pad_push_event (trans->sinkpad, event);
-
- return ret;
-}
-
-/* Takes the input buffer */
-static GstFlowReturn
-default_submit_input_buffer (GstBaseTransform * trans, gboolean is_discont,
- GstBuffer * inbuf)
-{
- GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
- GstBaseTransformPrivate *priv = trans->priv;
- GstFlowReturn ret = GST_FLOW_OK;
- GstClockTime running_time;
- GstClockTime timestamp;
-
- if (G_UNLIKELY (!gst_base_transform_reconfigure_unlocked (trans)))
- goto not_negotiated;
-
- if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
- GST_DEBUG_OBJECT (trans,
- "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT
- " and offset %" G_GUINT64_FORMAT, inbuf, gst_buffer_get_size (inbuf),
- GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)), GST_BUFFER_OFFSET (inbuf));
- else
- GST_DEBUG_OBJECT (trans,
- "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT
- " and offset NONE", inbuf, gst_buffer_get_size (inbuf),
- GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)));
-
- /* Don't allow buffer handling before negotiation, except in passthrough mode
- * or if the class doesn't implement a set_caps function (in which case it doesn't
- * care about caps)
- */
- if (!priv->negotiated && !priv->passthrough && (bclass->set_caps != NULL))
- goto not_negotiated;
-
- /* can only do QoS if the segment is in TIME */
- if (trans->segment.format != GST_FORMAT_TIME)
- goto no_qos;
-
- /* QOS is done on the running time of the buffer, get it now */
- timestamp = GST_BUFFER_TIMESTAMP (inbuf);
- running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
- timestamp);
-
- if (running_time != -1) {
- gboolean need_skip;
- GstClockTime earliest_time;
- gdouble proportion;
-
- /* lock for getting the QoS parameters that are set (in a different thread)
- * with the QOS events */
- GST_OBJECT_LOCK (trans);
- earliest_time = priv->earliest_time;
- proportion = priv->proportion;
- /* check for QoS, don't perform conversion for buffers
- * that are known to be late. */
- need_skip = priv->qos_enabled &&
- earliest_time != -1 && running_time <= earliest_time;
- GST_OBJECT_UNLOCK (trans);
-
- if (need_skip) {
- GstMessage *qos_msg;
- GstClockTime duration;
- guint64 stream_time;
- gint64 jitter;
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "skipping transform: qostime %"
- GST_TIME_FORMAT " <= %" GST_TIME_FORMAT,
- GST_TIME_ARGS (running_time), GST_TIME_ARGS (earliest_time));
-
- priv->dropped++;
-
- duration = GST_BUFFER_DURATION (inbuf);
- stream_time =
- gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
- timestamp);
- jitter = GST_CLOCK_DIFF (running_time, earliest_time);
-
- qos_msg =
- gst_message_new_qos (GST_OBJECT_CAST (trans), FALSE, running_time,
- stream_time, timestamp, duration);
- gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000);
- gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS,
- priv->processed, priv->dropped);
- gst_element_post_message (GST_ELEMENT_CAST (trans), qos_msg);
-
- /* mark discont for next buffer */
- priv->discont = TRUE;
- ret = GST_BASE_TRANSFORM_FLOW_DROPPED;
- goto skip;
- }
- }
-
-no_qos:
- /* Stash input buffer where the default generate_output
- * function can find it */
- if (trans->queued_buf)
- gst_buffer_unref (trans->queued_buf);
- trans->queued_buf = inbuf;
- return ret;
-skip:
- gst_buffer_unref (inbuf);
- return ret;
-
-not_negotiated:
- {
- gst_buffer_unref (inbuf);
- if (GST_PAD_IS_FLUSHING (trans->srcpad))
- return GST_FLOW_FLUSHING;
- return GST_FLOW_NOT_NEGOTIATED;
- }
-}
-
-static GstFlowReturn
-default_generate_output (GstBaseTransform * trans, GstBuffer ** outbuf)
-{
- GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
- GstBaseTransformPrivate *priv = trans->priv;
- GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *inbuf;
- gboolean want_in_place;
-
- /* Retrieve stashed input buffer, if the default submit_input_buffer
- * was run. Takes ownership back from there */
- inbuf = trans->queued_buf;
- trans->queued_buf = NULL;
-
- /* This default processing method needs one input buffer to feed to
- * the transform functions, we can't do anything without it */
- if (inbuf == NULL)
- return GST_FLOW_OK;
-
- /* first try to allocate an output buffer based on the currently negotiated
- * format. outbuf will contain a buffer suitable for doing the configured
- * transform after this function. */
- if (bclass->prepare_output_buffer == NULL)
- goto no_prepare;
-
- GST_DEBUG_OBJECT (trans, "calling prepare buffer");
- ret = bclass->prepare_output_buffer (trans, inbuf, outbuf);
-
- if (ret != GST_FLOW_OK || *outbuf == NULL)
- goto no_buffer;
-
- GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", inbuf,
- *outbuf);
-
- /* now perform the needed transform */
- if (priv->passthrough) {
- /* In passthrough mode, give transform_ip a look at the
- * buffer, without making it writable, or just push the
- * data through */
- if (bclass->transform_ip_on_passthrough && bclass->transform_ip) {
- GST_DEBUG_OBJECT (trans, "doing passthrough transform_ip");
- ret = bclass->transform_ip (trans, *outbuf);
- } else {
- GST_DEBUG_OBJECT (trans, "element is in passthrough");
- }
- } else {
- want_in_place = (bclass->transform_ip != NULL) && priv->always_in_place;
-
- if (want_in_place) {
- GST_DEBUG_OBJECT (trans, "doing inplace transform");
- ret = bclass->transform_ip (trans, *outbuf);
- } else {
- GST_DEBUG_OBJECT (trans, "doing non-inplace transform");
-
- if (bclass->transform)
- ret = bclass->transform (trans, inbuf, *outbuf);
- else
- ret = GST_FLOW_NOT_SUPPORTED;
- }
- }
-
- /* only unref input buffer if we allocated a new outbuf buffer. If we reused
- * the input buffer, no refcount is changed to keep the input buffer writable
- * when needed. */
- if (*outbuf != inbuf)
- gst_buffer_unref (inbuf);
-
- return ret;
-
- /* ERRORS */
-no_prepare:
- {
- gst_buffer_unref (inbuf);
- GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
- ("Sub-class has no prepare_output_buffer implementation"), (NULL));
- return GST_FLOW_NOT_SUPPORTED;
- }
-no_buffer:
- {
- gst_buffer_unref (inbuf);
- *outbuf = NULL;
- GST_WARNING_OBJECT (trans, "could not get buffer from pool: %s",
- gst_flow_get_name (ret));
- return ret;
- }
-}
-
-/* FIXME, getrange is broken, need to pull range from the other
- * end based on the transform_size result.
- */
-static GstFlowReturn
-gst_base_transform_getrange (GstPad * pad, GstObject * parent, guint64 offset,
- guint length, GstBuffer ** buffer)
-{
- GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (parent);
- GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent);
- GstBaseTransformPrivate *priv = trans->priv;
- GstFlowReturn ret;
- GstBuffer *inbuf = NULL;
- GstBuffer *outbuf = NULL;
-
- /* Try and generate a buffer, if the sub-class wants more data,
- * pull some and repeat until a buffer (or error) is produced */
- do {
- ret = klass->generate_output (trans, &outbuf);
-
- /* Consume the DROPPED return value and go get more data */
- if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED)
- ret = GST_FLOW_OK;
-
- if (ret != GST_FLOW_OK || outbuf != NULL)
- break;
-
- /* No buffer generated, try and pull data */
- ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto pull_error;
-
- if (klass->before_transform)
- klass->before_transform (trans, inbuf);
-
- /* Set discont flag so we can mark the next outgoing buffer */
- if (GST_BUFFER_IS_DISCONT (inbuf)) {
- GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", inbuf);
- priv->discont = TRUE;
- }
-
- /* FIXME: Input offsets and lengths need to be translated, as per
- * the FIXME above. For now, just advance somewhat */
- offset += gst_buffer_get_size (inbuf);
-
- ret = klass->submit_input_buffer (trans, priv->discont, inbuf);
- if (ret != GST_FLOW_OK) {
- if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED)
- ret = GST_FLOW_OK;
- goto done;
- }
- } while (ret == GST_FLOW_OK && outbuf == NULL);
-
- *buffer = outbuf;
- if (outbuf) {
- /* apply DISCONT flag if the buffer is not yet marked as such */
- if (priv->discont) {
- GST_DEBUG_OBJECT (trans, "we have a pending DISCONT");
- if (!GST_BUFFER_IS_DISCONT (outbuf)) {
- GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer");
- outbuf = gst_buffer_make_writable (outbuf);
- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- }
- priv->discont = FALSE;
- }
- priv->processed++;
- }
-done:
- return ret;
-
- /* ERRORS */
-pull_error:
- {
- GST_DEBUG_OBJECT (trans, "failed to pull a buffer: %s",
- gst_flow_get_name (ret));
- goto done;
- }
-}
-
-/* The flow of the chain function is the reverse of the
- * getrange() function - we have data, feed it to the sub-class
- * and then iterate, pushing buffers it generates until it either
- * wants more data or returns an error */
-static GstFlowReturn
-gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
-{
- GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent);
- GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
- GstBaseTransformPrivate *priv = trans->priv;
- GstFlowReturn ret;
- GstClockTime position = GST_CLOCK_TIME_NONE;
- GstClockTime timestamp, duration;
- GstBuffer *outbuf = NULL;
-
- timestamp = GST_BUFFER_TIMESTAMP (buffer);
- duration = GST_BUFFER_DURATION (buffer);
-
- /* calculate end position of the incoming buffer */
- if (timestamp != GST_CLOCK_TIME_NONE) {
- if (duration != GST_CLOCK_TIME_NONE)
- position = timestamp + duration;
- else
- position = timestamp;
- }
-
- if (klass->before_transform)
- klass->before_transform (trans, buffer);
-
- /* Set discont flag so we can mark the outgoing buffer */
- if (GST_BUFFER_IS_DISCONT (buffer)) {
- GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", buffer);
- priv->discont = TRUE;
- }
-
- /* Takes ownership of input buffer */
- ret = klass->submit_input_buffer (trans, priv->discont, buffer);
- if (ret != GST_FLOW_OK)
- goto done;
-
- do {
- outbuf = NULL;
-
- ret = klass->generate_output (trans, &outbuf);
-
- /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but
- * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */
- if (outbuf != NULL) {
- if (ret == GST_FLOW_OK) {
- GstClockTime position_out = GST_CLOCK_TIME_NONE;
-
- /* Remember last stop position */
- if (position != GST_CLOCK_TIME_NONE &&
- trans->segment.format == GST_FORMAT_TIME)
- trans->segment.position = position;
-
- if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf)) {
- position_out = GST_BUFFER_TIMESTAMP (outbuf);
- if (GST_BUFFER_DURATION_IS_VALID (outbuf))
- position_out += GST_BUFFER_DURATION (outbuf);
- } else if (position != GST_CLOCK_TIME_NONE) {
- position_out = position;
- }
- if (position_out != GST_CLOCK_TIME_NONE
- && trans->segment.format == GST_FORMAT_TIME)
- priv->position_out = position_out;
-
- /* apply DISCONT flag if the buffer is not yet marked as such */
- if (trans->priv->discont) {
- GST_DEBUG_OBJECT (trans, "we have a pending DISCONT");
- if (!GST_BUFFER_IS_DISCONT (outbuf)) {
- GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer");
- outbuf = gst_buffer_make_writable (outbuf);
- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- }
- priv->discont = FALSE;
- }
- priv->processed++;
-
- ret = gst_pad_push (trans->srcpad, outbuf);
- } else {
- GST_DEBUG_OBJECT (trans, "we got return %s", gst_flow_get_name (ret));
- gst_buffer_unref (outbuf);
- }
- }
- } while (ret == GST_FLOW_OK && outbuf != NULL);
-
-done:
- /* convert internal flow to OK and mark discont for the next buffer. */
- if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) {
- GST_DEBUG_OBJECT (trans, "dropped a buffer, marking DISCONT");
- priv->discont = TRUE;
- ret = GST_FLOW_OK;
- }
-
- return ret;
-}
-
-static void
-gst_base_transform_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstBaseTransform *trans;
-
- trans = GST_BASE_TRANSFORM_CAST (object);
-
- switch (prop_id) {
- case PROP_QOS:
- gst_base_transform_set_qos_enabled (trans, g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_base_transform_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstBaseTransform *trans;
-
- trans = GST_BASE_TRANSFORM_CAST (object);
-
- switch (prop_id) {
- case PROP_QOS:
- g_value_set_boolean (value, gst_base_transform_is_qos_enabled (trans));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* not a vmethod of anything, just an internal method */
-static gboolean
-gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
-{
- GstBaseTransformClass *bclass;
- GstBaseTransformPrivate *priv = trans->priv;
- gboolean result = TRUE;
-
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- if (active) {
- GstCaps *incaps, *outcaps;
-
- if (priv->pad_mode == GST_PAD_MODE_NONE && bclass->start)
- result &= bclass->start (trans);
-
- incaps = gst_pad_get_current_caps (trans->sinkpad);
- outcaps = gst_pad_get_current_caps (trans->srcpad);
-
- GST_OBJECT_LOCK (trans);
- if (incaps && outcaps)
- priv->have_same_caps =
- gst_caps_is_equal (incaps, outcaps) || priv->passthrough;
- else
- priv->have_same_caps = priv->passthrough;
- GST_DEBUG_OBJECT (trans, "have_same_caps %d", priv->have_same_caps);
- priv->negotiated = FALSE;
- trans->have_segment = FALSE;
- gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
- priv->position_out = GST_CLOCK_TIME_NONE;
- priv->proportion = 1.0;
- priv->earliest_time = -1;
- priv->discont = FALSE;
- priv->processed = 0;
- priv->dropped = 0;
- GST_OBJECT_UNLOCK (trans);
-
- if (incaps)
- gst_caps_unref (incaps);
- if (outcaps)
- gst_caps_unref (outcaps);
- } else {
- /* We must make sure streaming has finished before resetting things
- * and calling the ::stop vfunc */
- GST_PAD_STREAM_LOCK (trans->sinkpad);
- GST_PAD_STREAM_UNLOCK (trans->sinkpad);
-
- priv->have_same_caps = FALSE;
- /* We can only reset the passthrough mode if the instance told us to
- handle it in configure_caps */
- if (bclass->passthrough_on_same_caps) {
- gst_base_transform_set_passthrough (trans, FALSE);
- }
- gst_caps_replace (&priv->cache_caps1, NULL);
- gst_caps_replace (&priv->cache_caps2, NULL);
-
- /* Make sure any left over buffer is freed */
- gst_buffer_replace (&trans->queued_buf, NULL);
-
- if (priv->pad_mode != GST_PAD_MODE_NONE && bclass->stop)
- result &= bclass->stop (trans);
-
- gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL);
- }
-
- return result;
-}
-
-static gboolean
-gst_base_transform_sink_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active)
-{
- gboolean result = FALSE;
- GstBaseTransform *trans;
-
- trans = GST_BASE_TRANSFORM_CAST (parent);
-
- switch (mode) {
- case GST_PAD_MODE_PUSH:
- {
- result = gst_base_transform_activate (trans, active);
-
- if (result)
- trans->priv->pad_mode = active ? GST_PAD_MODE_PUSH : GST_PAD_MODE_NONE;
-
- break;
- }
- default:
- result = TRUE;
- break;
- }
- return result;
-}
-
-static gboolean
-gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
- GstPadMode mode, gboolean active)
-{
- gboolean result = FALSE;
- GstBaseTransform *trans;
-
- trans = GST_BASE_TRANSFORM_CAST (parent);
-
- switch (mode) {
- case GST_PAD_MODE_PULL:
- {
- result =
- gst_pad_activate_mode (trans->sinkpad, GST_PAD_MODE_PULL, active);
-
- if (result)
- result &= gst_base_transform_activate (trans, active);
-
- if (result)
- trans->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
- break;
- }
- default:
- result = TRUE;
- break;
- }
-
- return result;
-}
-
-/**
- * gst_base_transform_set_passthrough:
- * @trans: the #GstBaseTransform to set
- * @passthrough: boolean indicating passthrough mode.
- *
- * Set passthrough mode for this filter by default. This is mostly
- * useful for filters that do not care about negotiation.
- *
- * Always %TRUE for filters which don't implement either a transform
- * or transform_ip or generate_output method.
- *
- * MT safe.
- */
-void
-gst_base_transform_set_passthrough (GstBaseTransform * trans,
- gboolean passthrough)
-{
- GstBaseTransformClass *bclass;
-
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- GST_OBJECT_LOCK (trans);
- if (!passthrough) {
- if (bclass->transform_ip || bclass->transform || (bclass->generate_output
- && bclass->generate_output != default_generate_output))
- trans->priv->passthrough = FALSE;
- } else {
- trans->priv->passthrough = TRUE;
- }
-
- GST_DEBUG_OBJECT (trans, "set passthrough %d", trans->priv->passthrough);
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_is_passthrough:
- * @trans: the #GstBaseTransform to query
- *
- * See if @trans is configured as a passthrough transform.
- *
- * Returns: %TRUE if the transform is configured in passthrough mode.
- *
- * MT safe.
- */
-gboolean
-gst_base_transform_is_passthrough (GstBaseTransform * trans)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
-
- GST_OBJECT_LOCK (trans);
- result = trans->priv->passthrough;
- GST_OBJECT_UNLOCK (trans);
-
- return result;
-}
-
-/**
- * gst_base_transform_set_in_place:
- * @trans: the #GstBaseTransform to modify
- * @in_place: Boolean value indicating that we would like to operate
- * on in_place buffers.
- *
- * Determines whether a non-writable buffer will be copied before passing
- * to the transform_ip function.
- *
- * * Always %TRUE if no transform function is implemented.
- * * Always %FALSE if ONLY transform function is implemented.
- *
- * MT safe.
- */
-void
-gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place)
-{
- GstBaseTransformClass *bclass;
-
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
- GST_OBJECT_LOCK (trans);
-
- if (in_place) {
- if (bclass->transform_ip) {
- GST_DEBUG_OBJECT (trans, "setting in_place TRUE");
- trans->priv->always_in_place = TRUE;
- }
- } else {
- if (bclass->transform) {
- GST_DEBUG_OBJECT (trans, "setting in_place FALSE");
- trans->priv->always_in_place = FALSE;
- }
- }
-
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_is_in_place:
- * @trans: the #GstBaseTransform to query
- *
- * See if @trans is configured as a in_place transform.
- *
- * Returns: %TRUE if the transform is configured in in_place mode.
- *
- * MT safe.
- */
-gboolean
-gst_base_transform_is_in_place (GstBaseTransform * trans)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
-
- GST_OBJECT_LOCK (trans);
- result = trans->priv->always_in_place;
- GST_OBJECT_UNLOCK (trans);
-
- return result;
-}
-
-/**
- * gst_base_transform_update_qos:
- * @trans: a #GstBaseTransform
- * @proportion: the proportion
- * @diff: the diff against the clock
- * @timestamp: the timestamp of the buffer generating the QoS expressed in
- * running_time.
- *
- * Set the QoS parameters in the transform. This function is called internally
- * when a QOS event is received but subclasses can provide custom information
- * when needed.
- *
- * MT safe.
- */
-void
-gst_base_transform_update_qos (GstBaseTransform * trans,
- gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp));
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans,
- "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
- GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
-
- GST_OBJECT_LOCK (trans);
- trans->priv->proportion = proportion;
- trans->priv->earliest_time = timestamp + diff;
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_set_qos_enabled:
- * @trans: a #GstBaseTransform
- * @enabled: new state
- *
- * Enable or disable QoS handling in the transform.
- *
- * MT safe.
- */
-void
-gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "enabled: %d", enabled);
-
- GST_OBJECT_LOCK (trans);
- trans->priv->qos_enabled = enabled;
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_is_qos_enabled:
- * @trans: a #GstBaseTransform
- *
- * Queries if the transform will handle QoS.
- *
- * Returns: %TRUE if QoS is enabled.
- *
- * MT safe.
- */
-gboolean
-gst_base_transform_is_qos_enabled (GstBaseTransform * trans)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
-
- GST_OBJECT_LOCK (trans);
- result = trans->priv->qos_enabled;
- GST_OBJECT_UNLOCK (trans);
-
- return result;
-}
-
-/**
- * gst_base_transform_set_gap_aware:
- * @trans: a #GstBaseTransform
- * @gap_aware: New state
- *
- * If @gap_aware is %FALSE (the default), output buffers will have the
- * %GST_BUFFER_FLAG_GAP flag unset.
- *
- * If set to %TRUE, the element must handle output buffers with this flag set
- * correctly, i.e. it can assume that the buffer contains neutral data but must
- * unset the flag if the output is no neutral data.
- *
- * MT safe.
- */
-void
-gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- GST_OBJECT_LOCK (trans);
- trans->priv->gap_aware = gap_aware;
- GST_DEBUG_OBJECT (trans, "set gap aware %d", trans->priv->gap_aware);
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_set_prefer_passthrough:
- * @trans: a #GstBaseTransform
- * @prefer_passthrough: New state
- *
- * If @prefer_passthrough is %TRUE (the default), @trans will check and
- * prefer passthrough caps from the list of caps returned by the
- * transform_caps vmethod.
- *
- * If set to %FALSE, the element must order the caps returned from the
- * transform_caps function in such a way that the preferred format is
- * first in the list. This can be interesting for transforms that can do
- * passthrough transforms but prefer to do something else, like a
- * capsfilter.
- *
- * MT safe.
- *
- * Since: 1.0.1
- */
-void
-gst_base_transform_set_prefer_passthrough (GstBaseTransform * trans,
- gboolean prefer_passthrough)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- GST_OBJECT_LOCK (trans);
- trans->priv->prefer_passthrough = prefer_passthrough;
- GST_DEBUG_OBJECT (trans, "prefer passthrough %d", prefer_passthrough);
- GST_OBJECT_UNLOCK (trans);
-}
-
-/**
- * gst_base_transform_reconfigure_sink:
- * @trans: a #GstBaseTransform
- *
- * Instructs @trans to request renegotiation upstream. This function is
- * typically called after properties on the transform were set that
- * influence the input format.
- */
-void
-gst_base_transform_reconfigure_sink (GstBaseTransform * trans)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- /* push the renegotiate event */
- if (!gst_pad_push_event (GST_BASE_TRANSFORM_SINK_PAD (trans),
- gst_event_new_reconfigure ()))
- GST_DEBUG_OBJECT (trans, "Renegotiate event wasn't handled");
-}
-
-/**
- * gst_base_transform_reconfigure_src:
- * @trans: a #GstBaseTransform
- *
- * Instructs @trans to renegotiate a new downstream transform on the next
- * buffer. This function is typically called after properties on the transform
- * were set that influence the output format.
- */
-void
-gst_base_transform_reconfigure_src (GstBaseTransform * trans)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- gst_pad_mark_reconfigure (trans->srcpad);
-}
-
-/**
- * gst_base_transform_get_buffer_pool:
- * @trans: a #GstBaseTransform
- *
- * Returns: (nullable) (transfer full): the instance of the #GstBufferPool used
- * by @trans; free it after use
- */
-GstBufferPool *
-gst_base_transform_get_buffer_pool (GstBaseTransform * trans)
-{
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), NULL);
-
- if (trans->priv->pool)
- return gst_object_ref (trans->priv->pool);
-
- return NULL;
-}
-
-/**
- * gst_base_transform_get_allocator:
- * @trans: a #GstBaseTransform
- * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
- * used
- * @params: (out caller-allocates) (optional): the #GstAllocationParams of @allocator
- *
- * Lets #GstBaseTransform sub-classes know the memory @allocator
- * used by the base class and its @params.
- *
- * Unref the @allocator after use.
- */
-void
-gst_base_transform_get_allocator (GstBaseTransform * trans,
- GstAllocator ** allocator, GstAllocationParams * params)
-{
- g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
-
- if (allocator)
- *allocator = trans->priv->allocator ?
- gst_object_ref (trans->priv->allocator) : NULL;
-
- if (params)
- *params = trans->priv->params;
-}
-
-/**
- * gst_base_transform_update_src_caps:
- * @trans: a #GstBaseTransform
- * @updated_caps: An updated version of the srcpad caps to be pushed
- * downstream
- *
- * Updates the srcpad caps and sends the caps downstream. This function
- * can be used by subclasses when they have already negotiated their caps
- * but found a change in them (or computed new information). This way,
- * they can notify downstream about that change without losing any
- * buffer.
- *
- * Returns: %TRUE if the caps could be sent downstream %FALSE otherwise
- *
- * Since: 1.6
- */
-gboolean
-gst_base_transform_update_src_caps (GstBaseTransform * trans,
- GstCaps * updated_caps)
-{
- g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
-
- if (gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (trans),
- gst_event_new_caps (updated_caps))) {
- gst_pad_mark_reconfigure (trans->srcpad);
-
- return TRUE;
- }
-
- return FALSE;
-}
diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h
deleted file mode 100644
index 0457b89bb2..0000000000
--- a/libs/gst/base/gstbasetransform.h
+++ /dev/null
@@ -1,372 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BASE_TRANSFORM_H__
-#define __GST_BASE_TRANSFORM_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.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(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_TRANSFORM))
-#define GST_BASE_TRANSFORM_CAST(obj) ((GstBaseTransform *)(obj))
-
-/**
- * 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"
-
-/**
- * GST_BASE_TRANSFORM_SRC_PAD:
- * @obj: base transform instance
- *
- * Gives the pointer to the source #GstPad object of the element.
- */
-#define GST_BASE_TRANSFORM_SRC_PAD(obj) (GST_BASE_TRANSFORM_CAST (obj)->srcpad)
-
-/**
- * GST_BASE_TRANSFORM_SINK_PAD:
- * @obj: base transform instance
- *
- * Gives the pointer to the sink #GstPad object of the element.
- */
-#define GST_BASE_TRANSFORM_SINK_PAD(obj) (GST_BASE_TRANSFORM_CAST (obj)->sinkpad)
-
-/**
- * GST_BASE_TRANSFORM_FLOW_DROPPED:
- *
- * A #GstFlowReturn that can be returned from transform and transform_ip to
- * indicate that no output buffer was generated.
- */
-#define GST_BASE_TRANSFORM_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
-
-typedef struct _GstBaseTransform GstBaseTransform;
-typedef struct _GstBaseTransformClass GstBaseTransformClass;
-typedef struct _GstBaseTransformPrivate GstBaseTransformPrivate;
-
-/**
- * GstBaseTransform:
- *
- * The opaque #GstBaseTransform data structure.
- */
-struct _GstBaseTransform {
- GstElement element;
-
- /*< protected >*/
- /* source and sink pads */
- GstPad *sinkpad;
- GstPad *srcpad;
-
- /* MT-protected (with STREAM_LOCK) */
- gboolean have_segment;
- GstSegment segment;
- /* Default submit_input_buffer places the buffer here,
- * for consumption by the generate_output method: */
- GstBuffer *queued_buf;
-
- /*< private >*/
- GstBaseTransformPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING_LARGE-1];
-};
-
-/**
- * GstBaseTransformClass:
- * @parent_class: Element parent class
- * @passthrough_on_same_caps: If set to %TRUE, passthrough mode will be
- * automatically enabled if the caps are the same.
- * Set to %FALSE by default.
- * @transform_ip_on_passthrough: If set to %TRUE, @transform_ip will be called in
- * passthrough mode. The passed buffer might not be
- * writable. When %FALSE, neither @transform nor
- * @transform_ip will be called in passthrough mode.
- * Set to %TRUE by default.
- * @transform_caps: Optional. Given the pad in this direction and the given
- * caps, what caps are allowed on the other pad in this
- * element ?
- * @fixate_caps: Optional. Given the pad in this direction and the given
- * caps, fixate the caps on the other pad. The function takes
- * ownership of @othercaps and returns a fixated version of
- * @othercaps. @othercaps is not guaranteed to be writable.
- * @accept_caps: Optional.
- * Subclasses can override this method to check if @caps can be
- * handled by the element. The default implementation might not be
- * the most optimal way to check this in all cases.
- * @set_caps: Allows the subclass to be notified of the actual caps set.
- * @query: Optional.
- * Handle a requested query. Subclasses that implement this
- * must chain up to the parent if they didn't handle the
- * query
- * @decide_allocation: Setup the allocation parameters for allocating output
- * buffers. The passed in query contains the result of the
- * downstream allocation query. This function is only called
- * when not operating in passthrough mode. The default
- * implementation will remove all memory dependent metadata.
- * If there is a @filter_meta method implementation, it will
- * be called for all metadata API in the downstream query,
- * otherwise the metadata API is removed.
- * @filter_meta: Return %TRUE if the metadata API should be proposed in the
- * upstream allocation query. The default implementation is %NULL
- * and will cause all metadata to be removed.
- * @propose_allocation: Propose buffer allocation parameters for upstream elements.
- * This function must be implemented if the element reads or
- * writes the buffer content. The query that was passed to
- * the decide_allocation is passed in this method (or %NULL
- * when the element is in passthrough mode). The default
- * implementation will pass the query downstream when in
- * passthrough mode and will copy all the filtered metadata
- * API in non-passthrough mode.
- * @transform_size: Optional. Given the size of a buffer in the given direction
- * with the given caps, calculate the size in bytes of a buffer
- * on the other pad with the given other caps.
- * The default implementation uses get_unit_size and keeps
- * the number of units the same.
- * @get_unit_size: Required if the transform is not in-place.
- * Get the size in bytes of one unit for the given caps.
- * @start: Optional.
- * Called when the element starts processing.
- * Allows opening external resources.
- * @stop: Optional.
- * Called when the element stops processing.
- * Allows closing external resources.
- * @sink_event: Optional.
- * Event handler on the sink pad. The default implementation
- * handles the event and forwards it downstream.
- * @src_event: Optional.
- * Event handler on the source pad. The default implementation
- * handles the event and forwards it upstream.
- * @prepare_output_buffer: Optional.
- * Subclasses can override this to do their own
- * allocation of output buffers. Elements that only do
- * analysis can return a subbuffer or even just
- * return a reference to the input buffer (if in
- * passthrough mode). The default implementation will
- * use the negotiated allocator or bufferpool and
- * transform_size to allocate an output buffer or it
- * will return the input buffer in passthrough mode.
- * @copy_metadata: Optional.
- * Copy the metadata from the input buffer to the output buffer.
- * The default implementation will copy the flags, timestamps and
- * offsets of the buffer.
- * @transform_meta: Optional. Transform the metadata on the input buffer to the
- * output buffer. By default this method copies all meta without
- * tags. Subclasses can implement this method and return %TRUE if
- * the metadata is to be copied.
- * @before_transform: Optional.
- * This method is called right before the base class will
- * start processing. Dynamic properties or other delayed
- * configuration could be performed in this method.
- * @transform: Required if the element does not operate in-place.
- * Transforms one incoming buffer to one outgoing buffer.
- * The function is allowed to change size/timestamp/duration
- * of the outgoing buffer.
- * @transform_ip: Required if the element operates in-place.
- * Transform the incoming buffer in-place.
- * @submit_input_buffer: Function which accepts a new input buffer and pre-processes it.
- * The default implementation performs caps (re)negotiation, then
- * QoS if needed, and places the input buffer into the @queued_buf
- * member variable. If the buffer is dropped due to QoS, it returns
- * GST_BASE_TRANSFORM_FLOW_DROPPED. If this input buffer is not
- * contiguous with any previous input buffer, then @is_discont
- * is set to %TRUE. (Since: 1.6)
- * @generate_output: Called after each new input buffer is submitted repeatedly
- * until it either generates an error or fails to generate an output
- * buffer. The default implementation takes the contents of the
- * @queued_buf variable, generates an output buffer if needed
- * by calling the class @prepare_output_buffer, and then
- * calls either @transform or @transform_ip. Elements that don't
- * do 1-to-1 transformations of input to output buffers can either
- * return GST_BASE_TRANSFORM_FLOW_DROPPED or simply not generate
- * an output buffer until they are ready to do so. (Since: 1.6)
- *
- * Subclasses can override any of the available virtual methods or not, as
- * needed. At minimum either @transform or @transform_ip need to be overridden.
- * If the element can overwrite the input data with the results (data is of the
- * same type and quantity) it should provide @transform_ip.
- */
-struct _GstBaseTransformClass {
- GstElementClass parent_class;
-
- /*< public >*/
- gboolean passthrough_on_same_caps;
- gboolean transform_ip_on_passthrough;
-
- /* virtual methods for subclasses */
- GstCaps* (*transform_caps) (GstBaseTransform *trans,
- GstPadDirection direction,
- GstCaps *caps, GstCaps *filter);
- /**
- * GstBaseTransformClass::fixate_caps:
- * @othercaps: (transfer full):
- */
- GstCaps* (*fixate_caps) (GstBaseTransform *trans,
- GstPadDirection direction, GstCaps *caps,
- GstCaps *othercaps);
- gboolean (*accept_caps) (GstBaseTransform *trans, GstPadDirection direction,
- GstCaps *caps);
- gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
- GstCaps *outcaps);
- gboolean (*query) (GstBaseTransform *trans, GstPadDirection direction,
- GstQuery *query);
-
- /* decide allocation query for output buffers */
- gboolean (*decide_allocation) (GstBaseTransform *trans, GstQuery *query);
- gboolean (*filter_meta) (GstBaseTransform *trans, GstQuery *query,
- GType api, const GstStructure *params);
-
- /* propose allocation query parameters for input buffers */
- gboolean (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query,
- GstQuery *query);
-
- /**
- * GstBaseTransformClass::transform_size:
- * @othersize: (out):
- */
- gboolean (*transform_size) (GstBaseTransform *trans,
- GstPadDirection direction,
- GstCaps *caps, gsize size,
- GstCaps *othercaps, gsize *othersize);
-
- /**
- * GstBaseTransformClass::get_unit_size:
- * @size: (out):
- */
- gboolean (*get_unit_size) (GstBaseTransform *trans, GstCaps *caps,
- gsize *size);
-
- /* states */
- gboolean (*start) (GstBaseTransform *trans);
- gboolean (*stop) (GstBaseTransform *trans);
-
- /* sink and src pad event handlers */
- /**
- * GstBaseTransformClass::sink_event:
- * @event: (transfer full):
- */
- gboolean (*sink_event) (GstBaseTransform *trans, GstEvent *event);
- /**
- * GstBaseTransformClass::src_event:
- * @event: (transfer full):
- */
- gboolean (*src_event) (GstBaseTransform *trans, GstEvent *event);
-
- /**
- * GstBaseTransformClass::prepare_output_buffer:
- * @outbuf: (out):
- */
- GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
- GstBuffer *input, GstBuffer **outbuf);
-
- /* metadata */
- gboolean (*copy_metadata) (GstBaseTransform *trans, GstBuffer *input,
- GstBuffer *outbuf);
- gboolean (*transform_meta) (GstBaseTransform *trans, GstBuffer *outbuf,
- GstMeta *meta, GstBuffer *inbuf);
-
- void (*before_transform) (GstBaseTransform *trans, GstBuffer *buffer);
-
- /* transform */
- GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
- GstBuffer *outbuf);
- GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
-
- GstFlowReturn (*submit_input_buffer) (GstBaseTransform *trans, gboolean is_discont, GstBuffer *input);
-
- /**
- * GstBaseTransformClass::generate_output:
- * @outbuf: (out):
- */
- GstFlowReturn (*generate_output) (GstBaseTransform *trans, GstBuffer **outbuf);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE - 2];
-};
-
-GST_BASE_API
-GType gst_base_transform_get_type (void);
-
-GST_BASE_API
-void gst_base_transform_set_passthrough (GstBaseTransform *trans,
- gboolean passthrough);
-GST_BASE_API
-gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
-
-GST_BASE_API
-void gst_base_transform_set_in_place (GstBaseTransform *trans,
- gboolean in_place);
-GST_BASE_API
-gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
-
-GST_BASE_API
-void gst_base_transform_update_qos (GstBaseTransform *trans,
- gdouble proportion,
- GstClockTimeDiff diff,
- GstClockTime timestamp);
-GST_BASE_API
-void gst_base_transform_set_qos_enabled (GstBaseTransform *trans,
- gboolean enabled);
-GST_BASE_API
-gboolean gst_base_transform_is_qos_enabled (GstBaseTransform *trans);
-
-GST_BASE_API
-void gst_base_transform_set_gap_aware (GstBaseTransform *trans,
- gboolean gap_aware);
-GST_BASE_API
-void gst_base_transform_set_prefer_passthrough (GstBaseTransform *trans,
- gboolean prefer_passthrough);
-GST_BASE_API
-GstBufferPool * gst_base_transform_get_buffer_pool (GstBaseTransform *trans);
-
-GST_BASE_API
-void gst_base_transform_get_allocator (GstBaseTransform *trans,
- GstAllocator **allocator,
- GstAllocationParams *params);
-GST_BASE_API
-void gst_base_transform_reconfigure_sink (GstBaseTransform *trans);
-
-GST_BASE_API
-void gst_base_transform_reconfigure_src (GstBaseTransform *trans);
-
-GST_BASE_API
-gboolean gst_base_transform_update_src_caps (GstBaseTransform *trans,
- GstCaps *updated_caps);
-
-GST_BASE_API
-gboolean gst_base_transform_reconfigure (GstBaseTransform * trans);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseTransform, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_BASE_TRANSFORM_H__ */
diff --git a/libs/gst/base/gstbitreader-docs.h b/libs/gst/base/gstbitreader-docs.h
deleted file mode 100644
index d2842d6382..0000000000
--- a/libs/gst/base/gstbitreader-docs.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* GStreamer bit reader dummy header for gtk-doc
- * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* This header is not installed, it just contains stuff for gtk-doc to parse,
- * in particular docs and some dummy function declarations for the static
- * inline functions we generate via macros in gstbitreader.h.
- */
-
-#error "This header should never be included in code, it is only for gtk-doc"
-
-/**
- * gst_bit_reader_skip_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: the number of bits to skip
- *
- * Skips @nbits bits of the #GstBitReader instance without checking if there
- * are enough bits available in the bit reader.
- */
-void gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits);
-
-/**
- * gst_bit_reader_skip_to_byte_unchecked:
- * @reader: a #GstBitReader instance
- *
- * Skips until the next byte without checking if there are enough bits
- * available in the bit reader.
- */
-void gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader);
-
-/**
- * gst_bit_reader_get_bits_uint8_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position without
- * checking if there are enough bits available in the bit reader.
- *
- * Returns: unsigned 8 bit integer with the bits.
- */
-guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_peek_bits_uint8_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position without
- * checking if there are enough bits available in the bit reader
- *
- * Returns: unsigned 8 bit integer with the bits.
- */
-guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_get_bits_uint16_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position without
- * checking if there are enough bits available in the bit reader.
- *
- * Returns: unsigned 16 bit integer with the bits.
- */
-guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_peek_bits_uint16_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position without
- * checking if there are enough bits available in the bit reader
- *
- * Returns: unsigned 16 bit integer with the bits.
- */
-guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_get_bits_uint32_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position without
- * checking if there are enough bits available in the bit reader.
- *
- * Returns: unsigned 32 bit integer with the bits.
- */
-guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_peek_bits_uint32_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position without
- * checking if there are enough bits available in the bit reader
- *
- * Returns: unsigned 32 bit integer with the bits.
- */
-guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_get_bits_uint64_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position without
- * checking if there are enough bits available in the bit reader.
- *
- * Returns: unsigned 64 bit integer with the bits.
- */
-guint64 gst_bit_reader_get_bits_uint64_unchecked (GstBitReader *reader, guint nbits);
-
-/**
- * gst_bit_reader_peek_bits_uint64_unchecked:
- * @reader: a #GstBitReader instance
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position without
- * checking if there are enough bits available in the bit reader
- *
- * Returns: unsigned 64 bit integer with the bits.
- */
-guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, guint nbits);
-
diff --git a/libs/gst/base/gstbitreader.c b/libs/gst/base/gstbitreader.c
deleted file mode 100644
index db97ad51a2..0000000000
--- a/libs/gst/base/gstbitreader.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define GST_BIT_READER_DISABLE_INLINES
-#include "gstbitreader.h"
-
-#include <string.h>
-
-/**
- * SECTION:gstbitreader
- * @title: GstBitReader
- * @short_description: Reads any number of bits from a memory buffer
- * @symbols:
- * - gst_bit_reader_skip_unchecked
- * - gst_bit_reader_skip_to_byte_unchecked
- * - gst_bit_reader_get_bits_uint8_unchecked
- * - gst_bit_reader_peek_bits_uint8_unchecked
- * - gst_bit_reader_get_bits_uint16_unchecked
- * - gst_bit_reader_peek_bits_uint16_unchecked
- * - gst_bit_reader_get_bits_uint32_unchecked
- * - gst_bit_reader_peek_bits_uint32_unchecked
- * - gst_bit_reader_get_bits_uint64_unchecked
- * - gst_bit_reader_peek_bits_uint64_unchecked
- *
- * #GstBitReader provides a bit reader that can read any number of bits
- * from a memory buffer. It provides functions for reading any number of bits
- * into 8, 16, 32 and 64 bit variables.
- */
-
-/**
- * gst_bit_reader_new: (skip)
- * @data: (array length=size): Data from which the #GstBitReader
- * should read
- * @size: Size of @data in bytes
- *
- * Create a new #GstBitReader instance, which will read from @data.
- *
- * Free-function: gst_bit_reader_free
- *
- * Returns: (transfer full): a new #GstBitReader instance
- */
-GstBitReader *
-gst_bit_reader_new (const guint8 * data, guint size)
-{
- GstBitReader *ret = g_slice_new0 (GstBitReader);
-
- ret->data = data;
- ret->size = size;
-
- return ret;
-}
-
-/**
- * gst_bit_reader_free:
- * @reader: (in) (transfer full): a #GstBitReader instance
- *
- * Frees a #GstBitReader instance, which was previously allocated by
- * gst_bit_reader_new().
- */
-void
-gst_bit_reader_free (GstBitReader * reader)
-{
- g_return_if_fail (reader != NULL);
-
- g_slice_free (GstBitReader, reader);
-}
-
-/**
- * gst_bit_reader_init:
- * @reader: a #GstBitReader instance
- * @data: (in) (array length=size): data from which the bit reader should read
- * @size: Size of @data in bytes
- *
- * Initializes a #GstBitReader instance to read from @data. This function
- * can be called on already initialized instances.
- */
-void
-gst_bit_reader_init (GstBitReader * reader, const guint8 * data, guint size)
-{
- g_return_if_fail (reader != NULL);
-
- reader->data = data;
- reader->size = size;
- reader->byte = reader->bit = 0;
-}
-
-/**
- * gst_bit_reader_set_pos:
- * @reader: a #GstBitReader instance
- * @pos: The new position in bits
- *
- * Sets the new position of a #GstBitReader instance to @pos in bits.
- *
- * Returns: %TRUE if the position could be set successfully, %FALSE
- * otherwise.
- */
-gboolean
-gst_bit_reader_set_pos (GstBitReader * reader, guint pos)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
-
- if (pos > reader->size * 8)
- return FALSE;
-
- reader->byte = pos / 8;
- reader->bit = pos % 8;
-
- return TRUE;
-}
-
-/**
- * gst_bit_reader_get_pos:
- * @reader: a #GstBitReader instance
- *
- * Returns the current position of a #GstBitReader instance in bits.
- *
- * Returns: The current position of @reader in bits.
- */
-guint
-gst_bit_reader_get_pos (const GstBitReader * reader)
-{
- return _gst_bit_reader_get_pos_inline (reader);
-}
-
-/**
- * gst_bit_reader_get_remaining:
- * @reader: a #GstBitReader instance
- *
- * Returns the remaining number of bits of a #GstBitReader instance.
- *
- * Returns: The remaining number of bits of @reader instance.
- */
-guint
-gst_bit_reader_get_remaining (const GstBitReader * reader)
-{
- return _gst_bit_reader_get_remaining_inline (reader);
-}
-
-/**
- * gst_bit_reader_get_size:
- * @reader: a #GstBitReader instance
- *
- * Returns the total number of bits of a #GstBitReader instance.
- *
- * Returns: The total number of bits of @reader instance.
- */
-guint
-gst_bit_reader_get_size (const GstBitReader * reader)
-{
- return _gst_bit_reader_get_size_inline (reader);
-}
-
-/**
- * gst_bit_reader_skip:
- * @reader: a #GstBitReader instance
- * @nbits: the number of bits to skip
- *
- * Skips @nbits bits of the #GstBitReader instance.
- *
- * Returns: %TRUE if @nbits bits could be skipped, %FALSE otherwise.
- */
-gboolean
-gst_bit_reader_skip (GstBitReader * reader, guint nbits)
-{
- return _gst_bit_reader_skip_inline (reader, nbits);
-}
-
-/**
- * gst_bit_reader_skip_to_byte:
- * @reader: a #GstBitReader instance
- *
- * Skips until the next byte.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_bit_reader_skip_to_byte (GstBitReader * reader)
-{
- return _gst_bit_reader_skip_to_byte_inline (reader);
-}
-
-/**
- * gst_bit_reader_get_bits_uint8:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint8 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_get_bits_uint16:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_get_bits_uint32:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_get_bits_uint64:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_peek_bits_uint8:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint8 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_peek_bits_uint16:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_peek_bits_uint32:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_reader_peek_bits_uint64:
- * @reader: a #GstBitReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- * @nbits: number of bits to read
- *
- * Read @nbits bits into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-#define GST_BIT_READER_READ_BITS(bits) \
-gboolean \
-gst_bit_reader_peek_bits_uint##bits (const GstBitReader *reader, guint##bits *val, guint nbits) \
-{ \
- return _gst_bit_reader_peek_bits_uint##bits##_inline (reader, val, nbits); \
-} \
-\
-gboolean \
-gst_bit_reader_get_bits_uint##bits (GstBitReader *reader, guint##bits *val, guint nbits) \
-{ \
- return _gst_bit_reader_get_bits_uint##bits##_inline (reader, val, nbits); \
-}
-
-GST_BIT_READER_READ_BITS (8);
-GST_BIT_READER_READ_BITS (16);
-GST_BIT_READER_READ_BITS (32);
-GST_BIT_READER_READ_BITS (64);
diff --git a/libs/gst/base/gstbitreader.h b/libs/gst/base/gstbitreader.h
deleted file mode 100644
index 380edd3fe6..0000000000
--- a/libs/gst/base/gstbitreader.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BIT_READER_H__
-#define __GST_BIT_READER_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-/* FIXME: inline functions */
-
-G_BEGIN_DECLS
-
-#define GST_BIT_READER(reader) ((GstBitReader *) (reader))
-
-/**
- * GstBitReader:
- * @data: (array length=size): Data from which the bit reader will
- * read
- * @size: Size of @data in bytes
- * @byte: Current byte position
- * @bit: Bit position in the current byte
- *
- * A bit reader instance.
- */
-typedef struct {
- const guint8 *data;
- guint size;
-
- guint byte; /* Byte position */
- guint bit; /* Bit position in the current byte */
-
- /* < private > */
- gpointer _gst_reserved[GST_PADDING];
-} GstBitReader;
-
-GST_BASE_API
-GstBitReader * gst_bit_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_bit_reader_free (GstBitReader *reader);
-
-GST_BASE_API
-void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size);
-
-GST_BASE_API
-gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos);
-
-GST_BASE_API
-guint gst_bit_reader_get_pos (const GstBitReader *reader);
-
-GST_BASE_API
-guint gst_bit_reader_get_remaining (const GstBitReader *reader);
-
-GST_BASE_API
-guint gst_bit_reader_get_size (const GstBitReader *reader);
-
-GST_BASE_API
-gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader);
-
-GST_BASE_API
-gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
-
-/**
- * GST_BIT_READER_INIT:
- * @data: Data from which the #GstBitReader should read
- * @size: Size of @data in bytes
- *
- * A #GstBitReader must be initialized with this macro, before it can be
- * used. This macro can used be to initialize a variable, but it cannot
- * be assigned to a variable. In that case you have to use
- * gst_bit_reader_init().
- */
-#define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
-
-/* Unchecked variants */
-
-static inline void
-gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits)
-{
- reader->bit += nbits;
- reader->byte += reader->bit / 8;
- reader->bit = reader->bit % 8;
-}
-
-static inline void
-gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader)
-{
- if (reader->bit) {
- reader->bit = 0;
- reader->byte++;
- }
-}
-
-#define __GST_BIT_READER_READ_BITS_UNCHECKED(bits) \
-static inline guint##bits \
-gst_bit_reader_peek_bits_uint##bits##_unchecked (const GstBitReader *reader, guint nbits) \
-{ \
- guint##bits ret = 0; \
- const guint8 *data; \
- guint byte, bit; \
- \
- data = reader->data; \
- byte = reader->byte; \
- bit = reader->bit; \
- \
- while (nbits > 0) { \
- guint toread = MIN (nbits, 8 - bit); \
- \
- ret <<= toread; \
- ret |= (data[byte] & (0xff >> bit)) >> (8 - toread - bit); \
- \
- bit += toread; \
- if (bit >= 8) { \
- byte++; \
- bit = 0; \
- } \
- nbits -= toread; \
- } \
- \
- return ret; \
-} \
-\
-static inline guint##bits \
-gst_bit_reader_get_bits_uint##bits##_unchecked (GstBitReader *reader, guint nbits) \
-{ \
- guint##bits ret; \
- \
- ret = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \
- \
- gst_bit_reader_skip_unchecked (reader, nbits); \
- \
- return ret; \
-}
-
-__GST_BIT_READER_READ_BITS_UNCHECKED (8)
-__GST_BIT_READER_READ_BITS_UNCHECKED (16)
-__GST_BIT_READER_READ_BITS_UNCHECKED (32)
-__GST_BIT_READER_READ_BITS_UNCHECKED (64)
-
-#undef __GST_BIT_READER_READ_BITS_UNCHECKED
-
-/* unchecked variants -- do not use */
-
-static inline guint
-_gst_bit_reader_get_size_unchecked (const GstBitReader * reader)
-{
- return reader->size * 8;
-}
-
-static inline guint
-_gst_bit_reader_get_pos_unchecked (const GstBitReader * reader)
-{
- return reader->byte * 8 + reader->bit;
-}
-
-static inline guint
-_gst_bit_reader_get_remaining_unchecked (const GstBitReader * reader)
-{
- return reader->size * 8 - (reader->byte * 8 + reader->bit);
-}
-
-/* inlined variants -- do not use directly */
-static inline guint
-_gst_bit_reader_get_size_inline (const GstBitReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_bit_reader_get_size_unchecked (reader);
-}
-
-static inline guint
-_gst_bit_reader_get_pos_inline (const GstBitReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_bit_reader_get_pos_unchecked (reader);
-}
-
-static inline guint
-_gst_bit_reader_get_remaining_inline (const GstBitReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_bit_reader_get_remaining_unchecked (reader);
-}
-
-static inline gboolean
-_gst_bit_reader_skip_inline (GstBitReader * reader, guint nbits)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
-
- if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits)
- return FALSE;
-
- gst_bit_reader_skip_unchecked (reader, nbits);
-
- return TRUE;
-}
-
-static inline gboolean
-_gst_bit_reader_skip_to_byte_inline (GstBitReader * reader)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
-
- if (reader->byte > reader->size)
- return FALSE;
-
- gst_bit_reader_skip_to_byte_unchecked (reader);
-
- return TRUE;
-}
-
-#define __GST_BIT_READER_READ_BITS_INLINE(bits) \
-static inline gboolean \
-_gst_bit_reader_get_bits_uint##bits##_inline (GstBitReader *reader, guint##bits *val, guint nbits) \
-{ \
- g_return_val_if_fail (reader != NULL, FALSE); \
- g_return_val_if_fail (val != NULL, FALSE); \
- g_return_val_if_fail (nbits <= bits, FALSE); \
- \
- if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \
- return FALSE; \
-\
- *val = gst_bit_reader_get_bits_uint##bits##_unchecked (reader, nbits); \
- return TRUE; \
-} \
-\
-static inline gboolean \
-_gst_bit_reader_peek_bits_uint##bits##_inline (const GstBitReader *reader, guint##bits *val, guint nbits) \
-{ \
- g_return_val_if_fail (reader != NULL, FALSE); \
- g_return_val_if_fail (val != NULL, FALSE); \
- g_return_val_if_fail (nbits <= bits, FALSE); \
- \
- if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \
- return FALSE; \
-\
- *val = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \
- return TRUE; \
-}
-
-__GST_BIT_READER_READ_BITS_INLINE (8)
-__GST_BIT_READER_READ_BITS_INLINE (16)
-__GST_BIT_READER_READ_BITS_INLINE (32)
-__GST_BIT_READER_READ_BITS_INLINE (64)
-
-#undef __GST_BIT_READER_READ_BITS_INLINE
-
-#ifndef GST_BIT_READER_DISABLE_INLINES
-
-#define gst_bit_reader_get_size(reader) \
- _gst_bit_reader_get_size_inline (reader)
-#define gst_bit_reader_get_pos(reader) \
- _gst_bit_reader_get_pos_inline (reader)
-#define gst_bit_reader_get_remaining(reader) \
- _gst_bit_reader_get_remaining_inline (reader)
-
-/* we use defines here so we can add the G_LIKELY() */
-
-#define gst_bit_reader_skip(reader, nbits)\
- G_LIKELY (_gst_bit_reader_skip_inline(reader, nbits))
-#define gst_bit_reader_skip_to_byte(reader)\
- G_LIKELY (_gst_bit_reader_skip_to_byte_inline(reader))
-
-#define gst_bit_reader_get_bits_uint8(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_get_bits_uint8_inline (reader, val, nbits))
-#define gst_bit_reader_get_bits_uint16(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_get_bits_uint16_inline (reader, val, nbits))
-#define gst_bit_reader_get_bits_uint32(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_get_bits_uint32_inline (reader, val, nbits))
-#define gst_bit_reader_get_bits_uint64(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_get_bits_uint64_inline (reader, val, nbits))
-
-#define gst_bit_reader_peek_bits_uint8(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_peek_bits_uint8_inline (reader, val, nbits))
-#define gst_bit_reader_peek_bits_uint16(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_peek_bits_uint16_inline (reader, val, nbits))
-#define gst_bit_reader_peek_bits_uint32(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_peek_bits_uint32_inline (reader, val, nbits))
-#define gst_bit_reader_peek_bits_uint64(reader, val, nbits) \
- G_LIKELY (_gst_bit_reader_peek_bits_uint64_inline (reader, val, nbits))
-#endif
-
-G_END_DECLS
-
-#endif /* __GST_BIT_READER_H__ */
diff --git a/libs/gst/base/gstbitwriter-docs.h b/libs/gst/base/gstbitwriter-docs.h
deleted file mode 100644
index bc44db86a9..0000000000
--- a/libs/gst/base/gstbitwriter-docs.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * GStreamer bit writer dummy header for gtk-doc
- *
- * Copyright (C) 2013 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-/* This header is not installed, it just contains stuff for gtk-doc to parse,
- * in particular docs and some dummy function declarations for the static
- * inline functions we generate via macros in gstbitwriter.h.
- */
-
-#error "This header should never be included in code, it is only for gtk-doc"
-
-/**
- * gst_bit_writer_put_bits_uint8_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint8 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter without checking whether
- * there is enough space
- */
-void gst_bit_writer_put_bits_uint8_unchecked (GstBitWriter *bitwriter, guint8 value, guint nbits);
-
-/**
- * gst_bit_writer_put_bits_uint16_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint16 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter without checking whether
- * there is enough space
- */
-void gst_bit_writer_put_bits_uint16_unchecked (GstBitWriter *bitwriter, guint16 value, guint nbits);
-
-/**
- * gst_bit_writer_put_bits_uint32_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint32 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter without checking whether
- * there is enough space
- */
-void gst_bit_writer_put_bits_uint32_unchecked (GstBitWriter *bitwriter, guint32 value, guint nbits);
-
-/**
- * gst_bit_writer_put_bits_uint64_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint64 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter without checking whether
- * there is enough space
- */
-void gst_bit_writer_put_bits_uint64_unchecked (GstBitWriter *bitwriter, guint64 value, guint nbits);
-
-/**
- * gst_bit_writer_put_bytes_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @data: pointer of data to write
- * @nbytes: number of bytes to write
- *
- * Write @nbytes bytes of @data to #GstBitWriter without checking whether
- * there is enough space
- */
-void gst_bit_writer_put_bytes_unchecked (GstBitWriter *bitwriter, const guint8 *data, guint nbytes);
-
-/**
- * gst_bit_writer_align_bytes_unchecked:
- * @bitwriter: a #GstBitWriter instance
- * @trailing_bit: trailing bits of last byte, 0 or 1
- *
- * Write trailing bit to align last byte of @data without checking whether there
- * is enough space
- */
-void gst_bit_writer_align_bytes_unchecked (GstBitWriter *bitwriter, guint8 trailing_bit);
diff --git a/libs/gst/base/gstbitwriter.c b/libs/gst/base/gstbitwriter.c
deleted file mode 100644
index 7086c3c3d6..0000000000
--- a/libs/gst/base/gstbitwriter.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * gstbitwriter.c - bitstream writer
- *
- * Copyright (C) 2013 Intel Corporation
- * Copyright (C) 2018 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define GST_BIT_WRITER_DISABLE_INLINES
-#include "gstbitwriter.h"
-
-#include "gst/glib-compat-private.h"
-
-/**
- * SECTION:gstbitwriter
- * @title: GstBitWriter
- * @short_description: Writes any number of bits into a memory buffer
- *
- * #GstBitWriter provides a bit writer that can write any number of
- * bits into a memory buffer. It provides functions for writing any
- * number of bits into 8, 16, 32 and 64 bit variables.
- */
-
-/**
- * gst_bit_writer_new: (skip)
- *
- * Creates a new, empty #GstBitWriter instance.
- *
- * Free-function: gst_bit_writer_free
- *
- * Returns: (transfer full): a new, empty #GstByteWriter instance
- **/
-GstBitWriter *
-gst_bit_writer_new (void)
-{
- GstBitWriter *ret = g_slice_new0 (GstBitWriter);
-
- ret->owned = TRUE;
- ret->auto_grow = TRUE;
- return ret;
-}
-
-/**
- * gst_bit_writer_new_with_size: (skip)
- * @size: Initial size of data in bytes
- * @fixed: If %TRUE the data can't be reallocated
- *
- * Creates a #GstBitWriter instance with the given initial data size.
- *
- * Free-function: gst_bit_writer_free
- *
- * Returns: (transfer full): a new #GstBitWriter instance
- */
-GstBitWriter *
-gst_bit_writer_new_with_size (guint size, gboolean fixed)
-{
- GstBitWriter *ret = g_slice_new0 (GstBitWriter);
-
- gst_bit_writer_init_with_size (ret, size, fixed);
- return ret;
-}
-
-/**
- * gst_bit_writer_new_with_data: (skip)
- * @data: Memory area for writing
- * @size: Size of @data in bytes
- * @initialized: if %TRUE the complete data can be read from the beginning
- *
- * Creates a new #GstBitWriter instance with the given memory area. If
- * @initialized is %TRUE it is possible to read @size bits from the
- * #GstBitWriter from the beginning.
- *
- * Free-function: gst_bit_writer_free
- *
- * Returns: (transfer full): a new #GstBitWriter instance
- */
-GstBitWriter *
-gst_bit_writer_new_with_data (guint8 * data, guint size, gboolean initialized)
-{
- GstBitWriter *ret = g_slice_new0 (GstBitWriter);
-
- gst_bit_writer_init_with_data (ret, data, size, initialized);
-
- return ret;
-}
-
-/**
- * gst_bit_writer_init: (skip)
- * @bitwriter: #GstBitWriter instance
- *
- * Initializes @bitwriter to an empty instance.
- **/
-void
-gst_bit_writer_init (GstBitWriter * bitwriter)
-{
- g_return_if_fail (bitwriter != NULL);
-
- memset (bitwriter, 0, sizeof (GstBitWriter));
- bitwriter->owned = TRUE;
- bitwriter->auto_grow = TRUE;
-}
-
-/**
- * gst_bit_writer_init_with_size: (skip)
- * @bitwriter: #GstBitWriter instance
- * @size: the size on bytes to allocate for data
- * @fixed: If %TRUE the data can't be reallocated
- *
- * Initializes a #GstBitWriter instance and allocates the given data
- * @size.
- */
-void
-gst_bit_writer_init_with_size (GstBitWriter * bitwriter, guint size,
- gboolean fixed)
-{
- g_return_if_fail (bitwriter != NULL);
-
- gst_bit_writer_init (bitwriter);
-
- _gst_bit_writer_check_remaining (bitwriter, size << 3);
-
- bitwriter->auto_grow = !fixed;
-}
-
-/**
- * gst_bit_writer_init_with_data: (skip)
- * @bitwriter: #GstBitWriter instance
- * @data: (array length=size) (transfer none): Memory area for writing
- * @size: Size of @data in bytes
- * @initialized: If %TRUE the complete data can be read from the beginning
- *
- * Initializes @bitwriter with the given memory area @data. IF
- * @initialized is %TRUE it is possible to read @size bits from the
- * #GstBitWriter from the beginning.
- */
-void
-gst_bit_writer_init_with_data (GstBitWriter * bitwriter, guint8 * data,
- guint size, gboolean initialized)
-{
- g_return_if_fail (bitwriter != NULL);
-
- gst_bit_writer_init (bitwriter);
-
- bitwriter->data = data;
- bitwriter->bit_capacity = size * 8;
- bitwriter->bit_size = (initialized) ? size << 3 : 0;
- bitwriter->auto_grow = FALSE;
- bitwriter->owned = FALSE;
-}
-
-/**
- * gst_bit_writer_reset:
- * @bitwriter: #GstBitWriter instance
- *
- * Resets @bitwriter and frees the data if it's owned by @bitwriter.
- */
-void
-gst_bit_writer_reset (GstBitWriter * bitwriter)
-{
- g_return_if_fail (bitwriter != NULL);
-
- if (bitwriter->owned)
- g_free (bitwriter->data);
- memset (bitwriter, 0, sizeof (GstBitWriter));
-}
-
-/**
- * gst_bit_writer_reset_and_get_data:
- * @bitwriter: a #GstBitWriter instance
- *
- * Resets @bitwriter and returns the current data.
- *
- * Free-function: g_free
- *
- * Returns: (array) (transfer full): the current data. g_free() after
- * usage.
- **/
-guint8 *
-gst_bit_writer_reset_and_get_data (GstBitWriter * bitwriter)
-{
- guint8 *data;
-
- g_return_val_if_fail (bitwriter != NULL, NULL);
-
- data = bitwriter->data;
- if (bitwriter->owned)
- data = g_memdup2 (data, GST_ROUND_UP_8 (bitwriter->bit_size) >> 3);
- gst_bit_writer_reset (bitwriter);
-
- return data;
-}
-
-/**
- * gst_bit_writer_reset_and_get_buffer:
- * @bitwriter: a #GstBitWriter instance
- *
- * Resets @bitwriter and returns the current data as #GstBuffer.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full): a new allocated #GstBuffer wrapping the
- * current data. gst_buffer_unref() after usage.
- **/
-GstBuffer *
-gst_bit_writer_reset_and_get_buffer (GstBitWriter * bitwriter)
-{
- GstBuffer *buffer;
- gpointer data;
- gsize size;
- gboolean owned;
-
- g_return_val_if_fail (bitwriter != NULL, NULL);
-
- owned = bitwriter->owned;
-
- size = GST_ROUND_UP_8 (bitwriter->bit_size) >> 3;
- data = gst_bit_writer_reset_and_get_data (bitwriter);
-
- /* we cannot rely on buffers allocated externally, thus let's dup
- * the data */
- if (data && !owned)
- data = g_memdup2 (data, size);
-
- buffer = gst_buffer_new ();
- if (data != NULL) {
- gst_buffer_append_memory (buffer,
- gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
- }
-
- return buffer;
-}
-
-/**
- * gst_bit_writer_free:
- * @bitwriter: (in) (transfer full): #GstBitWriter instance
- *
- * Frees @bitwriter and the allocated data inside.
- */
-void
-gst_bit_writer_free (GstBitWriter * bitwriter)
-{
- g_return_if_fail (bitwriter != NULL);
-
- gst_bit_writer_reset (bitwriter);
- g_slice_free (GstBitWriter, bitwriter);
-}
-
-/**
- * gst_bit_writer_free_and_get_data:
- * @bitwriter: (in) (transfer full): #GstBitWriter instance
- *
- * Frees @bitwriter without destroying the internal data, which is
- * returned.
- *
- * Free-function: g_free
- *
- * Returns: (array) (transfer full): the current data. g_free() after
- * usage.
- **/
-guint8 *
-gst_bit_writer_free_and_get_data (GstBitWriter * bitwriter)
-{
- guint8 *data;
-
- g_return_val_if_fail (bitwriter != NULL, NULL);
-
- data = gst_bit_writer_reset_and_get_data (bitwriter);
- g_slice_free (GstBitWriter, bitwriter);
-
- return data;
-}
-
-/**
- * gst_bit_writer_free_and_get_buffer:
- * @bitwriter: (in) (transfer full): #GstBitWriter instance
- *
- * Frees @bitwriter without destroying the internal data, which is
- * returned as #GstBuffer.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full): a new allocated #GstBuffer wrapping the
- * data inside. gst_buffer_unref() after usage.
- **/
-GstBuffer *
-gst_bit_writer_free_and_get_buffer (GstBitWriter * bitwriter)
-{
- GstBuffer *buffer;
-
- g_return_val_if_fail (bitwriter != NULL, NULL);
-
- buffer = gst_bit_writer_reset_and_get_buffer (bitwriter);
- g_slice_free (GstBitWriter, bitwriter);
-
- return buffer;
-}
-
-/**
- * gst_bit_writer_get_size:
- * @bitwriter: a #GstBitWriter instance
- *
- * Get size of written @data
- *
- * Returns: size of bits written in @data
- */
-guint
-gst_bit_writer_get_size (const GstBitWriter * bitwriter)
-{
- return _gst_bit_writer_get_size_inline (bitwriter);
-}
-
-/**
- * gst_bit_writer_get_data:
- * @bitwriter: a #GstBitWriter instance
- *
- * Get written data pointer
- *
- * Returns: data pointer
- */
-guint8 *
-gst_bit_writer_get_data (const GstBitWriter * bitwriter)
-{
- return _gst_bit_writer_get_data_inline (bitwriter);
-}
-
-/**
- * gst_bit_writer_get_pos:
- * @bitwriter: a #GstBitWriter instance
- * @pos: The new position in bits
- *
- * Set the new position of data end which should be the new size of @data.
- *
- * Returns: %TRUE if successful, %FALSE otherwise
- */
-gboolean
-gst_bit_writer_set_pos (GstBitWriter * bitwriter, guint pos)
-{
- return _gst_bit_writer_set_pos_inline (bitwriter, pos);
-}
-
-/**
- * gst_bit_writer_put_bits_uint8:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint8 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_writer_put_bits_uint16:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint16 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_writer_put_bits_uint32:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint32 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_bit_writer_put_bits_uint64:
- * @bitwriter: a #GstBitWriter instance
- * @value: value of #guint64 to write
- * @nbits: number of bits to write
- *
- * Write @nbits bits of @value to #GstBitWriter.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/* *INDENT-OFF* */
-#define GST_BIT_WRITER_WRITE_BITS(bits) \
-gboolean \
-gst_bit_writer_put_bits_uint##bits (GstBitWriter *bitwriter, guint##bits value, guint nbits) \
-{ \
- return _gst_bit_writer_put_bits_uint##bits##_inline (bitwriter, value, nbits); \
-}
-
-GST_BIT_WRITER_WRITE_BITS (8)
-GST_BIT_WRITER_WRITE_BITS (16)
-GST_BIT_WRITER_WRITE_BITS (32)
-GST_BIT_WRITER_WRITE_BITS (64)
-#undef GST_BIT_WRITER_WRITE_BITS
-/* *INDENT-ON* */
-
-/**
- * gst_bit_writer_put_bytes:
- * @bitwriter: a #GstBitWriter instance
- * @data: pointer of data to write
- * @nbytes: number of bytes to write
- *
- * Write @nbytes bytes of @data to #GstBitWriter.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_bit_writer_put_bytes (GstBitWriter * bitwriter, const guint8 * data,
- guint nbytes)
-{
- return _gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes);
-}
-
-/**
- * gst_bit_writer_align_bytes:
- * @bitwriter: a #GstBitWriter instance
- * @trailing_bit: trailing bits of last byte, 0 or 1
- *
- * Write trailing bit to align last byte of @data. @trailing_bit can
- * only be 1 or 0.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_bit_writer_align_bytes (GstBitWriter * bitwriter, guint8 trailing_bit)
-{
- return _gst_bit_writer_align_bytes_inline (bitwriter, trailing_bit);
-}
diff --git a/libs/gst/base/gstbitwriter.h b/libs/gst/base/gstbitwriter.h
deleted file mode 100644
index 8a860e8e08..0000000000
--- a/libs/gst/base/gstbitwriter.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * gstbitwriter.h - bitstream writer
- *
- * Copyright (C) 2013 Intel Corporation
- * Copyright (C) 2018 Igalia, S. L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef GST_BIT_WRITER_H
-#define GST_BIT_WRITER_H
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-#include <string.h>
-
-G_BEGIN_DECLS
-
-#define GST_BIT_WRITER_DATA(writer) ((writer)->data)
-#define GST_BIT_WRITER_BIT_SIZE(writer) ((writer)->bit_size)
-#define GST_BIT_WRITER(writer) ((GstBitWriter *) (writer))
-
-typedef struct _GstBitWriter GstBitWriter;
-
-/**
- * GstBitWriter:
- * @data: Allocated @data for bit writer to write
- * @bit_size: Size of written @data in bits
- *
- * A bit writer instance.
- *
- * Since: 1.16
- */
-struct _GstBitWriter
-{
- guint8 *data;
- guint bit_size;
-
- /*< private >*/
- guint bit_capacity; /* Capacity of the allocated data */
- gboolean auto_grow; /* Whether space can auto grow */
- gboolean owned;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_BASE_API
-GstBitWriter * gst_bit_writer_new (void) G_GNUC_MALLOC;
-
-GST_BASE_API
-GstBitWriter * gst_bit_writer_new_with_size (guint32 size, gboolean fixed) G_GNUC_MALLOC;
-
-GST_BASE_API
-GstBitWriter * gst_bit_writer_new_with_data (guint8 *data, guint size,
- gboolean initialized) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_bit_writer_free (GstBitWriter *bitwriter);
-
-GST_BASE_API
-guint8 * gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter);
-
-GST_BASE_API
-GstBuffer * gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter);
-
-GST_BASE_API
-void gst_bit_writer_init (GstBitWriter *bitwriter);
-
-GST_BASE_API
-void gst_bit_writer_init_with_size (GstBitWriter *bitwriter,
- guint32 size, gboolean fixed);
-
-GST_BASE_API
-void gst_bit_writer_init_with_data (GstBitWriter *bitwriter, guint8 *data,
- guint size, gboolean initialized);
-
-GST_BASE_API
-void gst_bit_writer_reset (GstBitWriter *bitwriter);
-
-GST_BASE_API
-guint8 * gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter);
-
-GST_BASE_API
-GstBuffer * gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter);
-
-GST_BASE_API
-guint gst_bit_writer_get_size (const GstBitWriter *bitwriter);
-
-GST_BASE_API
-guint8 * gst_bit_writer_get_data (const GstBitWriter *bitwriter);
-
-GST_BASE_API
-gboolean gst_bit_writer_set_pos (GstBitWriter *bitwriter, guint pos);
-
-GST_BASE_API
-guint gst_bit_writer_get_remaining (const GstBitWriter *bitwriter);
-
-GST_BASE_API
-gboolean gst_bit_writer_put_bits_uint8 (GstBitWriter *bitwriter, guint8 value,
- guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_writer_put_bits_uint16 (GstBitWriter *bitwriter, guint16 value,
- guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_writer_put_bits_uint32 (GstBitWriter *bitwriter, guint32 value,
- guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_writer_put_bits_uint64 (GstBitWriter *bitwriter, guint64 value,
- guint nbits);
-
-GST_BASE_API
-gboolean gst_bit_writer_put_bytes (GstBitWriter *bitwriter, const guint8 *data,
- guint nbytes);
-
-GST_BASE_API
-gboolean gst_bit_writer_align_bytes (GstBitWriter *bitwriter, guint8 trailing_bit);
-
-static const guint8 _gst_bit_writer_bit_filling_mask[9] = {
- 0x00, 0x01, 0x03, 0x07,
- 0x0F, 0x1F, 0x3F, 0x7F,
- 0xFF
-};
-
-/* Aligned to 256 bytes */
-#define __GST_BITS_WRITER_ALIGNMENT_MASK 2047
-#define __GST_BITS_WRITER_ALIGNED(bitsize) \
- (((bitsize) + __GST_BITS_WRITER_ALIGNMENT_MASK)&(~__GST_BITS_WRITER_ALIGNMENT_MASK))
-
-static inline gboolean
-_gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits)
-{
- guint32 new_bit_size = bits + bitwriter->bit_size;
- guint32 clear_pos;
-
- g_assert (bitwriter->bit_size <= bitwriter->bit_capacity);
- if (new_bit_size <= bitwriter->bit_capacity)
- return TRUE;
-
- if (!bitwriter->auto_grow)
- return FALSE;
-
- /* auto grow space */
- new_bit_size = __GST_BITS_WRITER_ALIGNED (new_bit_size);
- g_assert (new_bit_size
- && ((new_bit_size & __GST_BITS_WRITER_ALIGNMENT_MASK) == 0));
- clear_pos = ((bitwriter->bit_size + 7) >> 3);
- bitwriter->data = (guint8 *) g_realloc (bitwriter->data, (new_bit_size >> 3));
- memset (bitwriter->data + clear_pos, 0, (new_bit_size >> 3) - clear_pos);
- bitwriter->bit_capacity = new_bit_size;
- return TRUE;
-}
-
-#undef __GST_BITS_WRITER_ALIGNMENT_MASK
-#undef __GST_BITS_WRITER_ALIGNED
-
-#define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \
-static inline void \
-gst_bit_writer_put_bits_uint##bits##_unchecked( \
- GstBitWriter *bitwriter, \
- guint##bits value, \
- guint nbits \
-) \
-{ \
- guint byte_pos, bit_offset; \
- guint8 *cur_byte; \
- guint fill_bits; \
- \
- byte_pos = (bitwriter->bit_size >> 3); \
- bit_offset = (bitwriter->bit_size & 0x07); \
- cur_byte = bitwriter->data + byte_pos; \
- g_assert (nbits <= bits); \
- g_assert( bit_offset < 8 && \
- bitwriter->bit_size <= bitwriter->bit_capacity); \
- \
- while (nbits) { \
- fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \
- nbits -= fill_bits; \
- bitwriter->bit_size += fill_bits; \
- \
- *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \
- << (8 - bit_offset - fill_bits)); \
- ++cur_byte; \
- bit_offset = 0; \
- } \
- g_assert(cur_byte <= \
- (bitwriter->data + (bitwriter->bit_capacity >> 3))); \
-}
-
-__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (8)
-__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (16)
-__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (32)
-__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (64)
-#undef __GST_BIT_WRITER_WRITE_BITS_UNCHECKED
-
-static inline guint
-gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter)
-{
- return GST_BIT_WRITER_BIT_SIZE (bitwriter);
-}
-
-static inline guint8 *
-gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter)
-{
- return GST_BIT_WRITER_DATA (bitwriter);
-}
-
-static inline gboolean
-gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos)
-{
- GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos;
- return TRUE;
-}
-
-static inline guint
-gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter)
-{
- return bitwriter->bit_capacity - bitwriter->bit_size;
-}
-
-static inline void
-gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter,
- const guint8 * data, guint nbytes)
-{
- if ((bitwriter->bit_size & 0x07) == 0) {
- memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes);
- bitwriter->bit_size += (nbytes << 3);
- } else {
- g_assert (0);
- while (nbytes) {
- gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8);
- --nbytes;
- ++data;
- }
- }
-}
-
-static inline void
-gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter,
- guint8 trailing_bit)
-{
- guint32 bit_offset, bit_left;
- guint8 value = 0;
-
- bit_offset = (bitwriter->bit_size & 0x07);
- if (!bit_offset)
- return;
-
- bit_left = 8 - bit_offset;
- if (trailing_bit)
- value = _gst_bit_writer_bit_filling_mask[bit_left];
- gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left);
-}
-
-#define __GST_BIT_WRITER_WRITE_BITS_INLINE(bits) \
-static inline gboolean \
-_gst_bit_writer_put_bits_uint##bits##_inline( \
- GstBitWriter *bitwriter, \
- guint##bits value, \
- guint nbits \
-) \
-{ \
- g_return_val_if_fail(bitwriter != NULL, FALSE); \
- g_return_val_if_fail(nbits != 0, FALSE); \
- g_return_val_if_fail(nbits <= bits, FALSE); \
- \
- if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \
- return FALSE; \
- gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \
- return TRUE; \
-}
-
-__GST_BIT_WRITER_WRITE_BITS_INLINE (8)
-__GST_BIT_WRITER_WRITE_BITS_INLINE (16)
-__GST_BIT_WRITER_WRITE_BITS_INLINE (32)
-__GST_BIT_WRITER_WRITE_BITS_INLINE (64)
-#undef __GST_BIT_WRITER_WRITE_BITS_INLINE
-
-static inline guint
-_gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter)
-{
- g_return_val_if_fail (bitwriter != NULL, 0);
-
- return gst_bit_writer_get_size_unchecked (bitwriter);
-}
-
-static inline guint8 *
-_gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter)
-{
- g_return_val_if_fail (bitwriter != NULL, NULL);
-
- return gst_bit_writer_get_data_unchecked (bitwriter);
-}
-
-static inline gboolean
-_gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos)
-{
- g_return_val_if_fail (bitwriter != NULL, FALSE);
- g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE);
-
- return gst_bit_writer_set_pos_unchecked (bitwriter, pos);
-}
-
-static inline guint
-_gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter)
-{
- g_return_val_if_fail (bitwriter != NULL, 0);
- g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0);
-
- return gst_bit_writer_get_remaining_unchecked (bitwriter);
-}
-
-static inline gboolean
-_gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter,
- const guint8 * data, guint nbytes)
-{
- g_return_val_if_fail (bitwriter != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (nbytes, FALSE);
-
- if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8))
- return FALSE;
-
- gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes);
- return TRUE;
-}
-
-static inline gboolean
-_gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter,
- guint8 trailing_bit)
-{
- g_return_val_if_fail (bitwriter != NULL, FALSE);
- g_return_val_if_fail ((trailing_bit == 0 || trailing_bit == 1), FALSE);
- g_return_val_if_fail (((bitwriter->bit_size + 7) & (~7)) <=
- bitwriter->bit_capacity, FALSE);
-
- gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit);
- return TRUE;
-}
-
-#ifndef GST_BIT_WRITER_DISABLE_INLINES
-#define gst_bit_writer_get_size(bitwriter) \
- _gst_bit_writer_get_size_inline(bitwriter)
-#define gst_bit_writer_get_data(bitwriter) \
- _gst_bit_writer_get_data_inline(bitwriter)
-#define gst_bit_writer_set_pos(bitwriter, pos) \
- G_LIKELY (_gst_bit_writer_set_pos_inline (bitwriter, pos))
-#define gst_bit_writer_get_remaining(bitwriter) \
- _gst_bit_writer_get_remaining_inline(bitwriter)
-
-#define gst_bit_writer_put_bits_uint8(bitwriter, value, nbits) \
- G_LIKELY (_gst_bit_writer_put_bits_uint8_inline (bitwriter, value, nbits))
-#define gst_bit_writer_put_bits_uint16(bitwriter, value, nbits) \
- G_LIKELY (_gst_bit_writer_put_bits_uint16_inline (bitwriter, value, nbits))
-#define gst_bit_writer_put_bits_uint32(bitwriter, value, nbits) \
- G_LIKELY (_gst_bit_writer_put_bits_uint32_inline (bitwriter, value, nbits))
-#define gst_bit_writer_put_bits_uint64(bitwriter, value, nbits) \
- G_LIKELY (_gst_bit_writer_put_bits_uint64_inline (bitwriter, value, nbits))
-
-#define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \
- G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes))
-
-#define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \
- G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit))
-#endif
-
-G_END_DECLS
-
-#endif /* GST_BIT_WRITER_H */
diff --git a/libs/gst/base/gstbytereader-docs.h b/libs/gst/base/gstbytereader-docs.h
deleted file mode 100644
index b582c3f744..0000000000
--- a/libs/gst/base/gstbytereader-docs.h
+++ /dev/null
@@ -1,552 +0,0 @@
-/* GStreamer byte reader dummy header for gtk-doc
- * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* This header is not installed, it just contains stuff for gtk-doc to parse,
- * in particular docs and some dummy function declarations for the static
- * inline functions we generate via macros in gstbytereader.h.
- */
-
-#error "This header should never be included in code, it is only for gtk-doc"
-
-/**
- * gst_byte_reader_skip_unchecked:
- * @reader: a #GstByteReader instance
- * @nbytes: the number of bytes to skip
- *
- * Skips @nbytes bytes of the #GstByteReader instance without checking if
- * there are enough bytes available in the byte reader.
- */
-void gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes);
-
-/**
- * gst_byte_reader_get_uint8_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 8 bit integer without checking if there are enough bytes
- * available in the byte reader and update the current position.
- *
- * Returns: unsigned 8 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint8_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 8 bit integer without checking if there are enough bytes
- * available in the byte reader, but do not advance the current read position.
- *
- * Returns: unsigned 8 bit integer.
- */
-/**
- * gst_byte_reader_get_int8_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an signed 8 bit integer without checking if there are enough bytes
- * available in the byte reader and update the current position.
- *
- * Returns: signed 8 bit integer.
- */
-/**
- * gst_byte_reader_peek_int8_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an signed 8 bit integer without checking if there are enough bytes
- * available in the byte reader, but do not advance the current read position.
- *
- * Returns: signed 8 bit integer.
- */
-guint8 gst_byte_reader_get_uint8_unchecked (GstByteReader * reader);
-guint8 gst_byte_reader_peek_uint8_unchecked (GstByteReader * reader);
-gint8 gst_byte_reader_get_int8_unchecked (GstByteReader * reader);
-gint8 gst_byte_reader_peek_int8_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_get_uint16_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 16 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 16 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint16_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 16 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 16 bit integer.
- */
-/**
- * gst_byte_reader_get_uint16_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 16 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 16 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint16_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 16 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 16 bit integer.
- */
-/**
- * gst_byte_reader_get_int16_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 16 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 16 bit integer.
- */
-/**
- * gst_byte_reader_peek_int16_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 16 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 16 bit integer.
- */
-/**
- * gst_byte_reader_get_int16_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 16 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 16 bit integer.
- */
-/**
- * gst_byte_reader_peek_int16_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 16 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 16 bit integer.
- */
-guint16 gst_byte_reader_get_uint16_le_unchecked (GstByteReader * reader);
-guint16 gst_byte_reader_get_uint16_be_unchecked (GstByteReader * reader);
-guint16 gst_byte_reader_peek_uint16_le_unchecked (GstByteReader * reader);
-guint16 gst_byte_reader_peek_uint16_be_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_get_int16_le_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_get_int16_be_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_peek_int16_le_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_peek_int16_be_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_get_uint24_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 24 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 24 bit integer (as guint32)
- */
-/**
- * gst_byte_reader_peek_uint24_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 24 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 24 bit integer (as guint32)
- */
-/**
- * gst_byte_reader_get_uint24_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 24 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 24 bit integer (as guint32)
- */
-/**
- * gst_byte_reader_peek_uint24_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 24 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 24 bit integer (as guint32)
- */
-/**
- * gst_byte_reader_get_int24_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 24 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 24 bit integer (as gint32)
- */
-/**
- * gst_byte_reader_peek_int24_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 24 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 24 bit integer (as gint32)
- */
-/**
- * gst_byte_reader_get_int24_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 24 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 24 bit integer (as gint32)
- */
-/**
- * gst_byte_reader_peek_int24_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 24 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 24 bit integer (as gint32)
- */
-guint32 gst_byte_reader_get_uint24_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_get_uint24_be_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_peek_uint24_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_peek_uint24_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int24_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int24_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int24_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int24_be_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_get_uint32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 32 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 32 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 32 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 32 bit integer.
- */
-/**
- * gst_byte_reader_get_uint32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 32 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 32 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 32 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 32 bit integer.
- */
-/**
- * gst_byte_reader_get_int32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 32 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 32 bit integer.
- */
-/**
- * gst_byte_reader_peek_int32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 32 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 32 bit integer.
- */
-/**
- * gst_byte_reader_get_int32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 32 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 32 bit integer.
- */
-/**
- * gst_byte_reader_peek_int32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 32 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 32 bit integer.
- */
-guint32 gst_byte_reader_get_uint32_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_get_uint32_be_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_peek_uint32_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_peek_uint32_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int32_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int32_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int32_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int32_be_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_get_uint64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 64 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 64 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 64 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 64 bit integer.
- */
-/**
- * gst_byte_reader_get_uint64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 64 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: unsigned 64 bit integer.
- */
-/**
- * gst_byte_reader_peek_uint64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read an unsigned 64 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: unsigned 64 bit integer.
- */
-/**
- * gst_byte_reader_get_int64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 64 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 64 bit integer.
- */
-/**
- * gst_byte_reader_peek_int64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 64 bit integer in little endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 64 bit integer.
- */
-/**
- * gst_byte_reader_get_int64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 64 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader and update the
- * current position.
- *
- * Returns: signed 64 bit integer.
- */
-/**
- * gst_byte_reader_peek_int64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a signed 64 bit integer in big endian format without checking
- * if there are enough bytes available in the byte reader, but do not advance
- * the current position.
- *
- * Returns: signed 64 bit integer.
- */
-guint64 gst_byte_reader_get_uint64_le_unchecked (GstByteReader * reader);
-guint64 gst_byte_reader_get_uint64_be_unchecked (GstByteReader * reader);
-guint64 gst_byte_reader_peek_uint64_le_unchecked (GstByteReader * reader);
-guint64 gst_byte_reader_peek_uint64_be_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_get_int64_le_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_get_int64_be_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_peek_int64_le_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_peek_int64_be_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_get_float32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 32 bit little endian float without checking if there is enough
- * data available and update the current position.
- *
- * Returns: floating point value read
- */
-/**
- * gst_byte_reader_peek_float32_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 32 bit little endian float without checking if there is enough
- * data available, but keep the current position.
- *
- * Returns: floating point value read
- */
-/**
- * gst_byte_reader_get_float32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 32 bit big endian float without checking if there is enough
- * data available and update the current position.
- *
- * Returns: floating point value read
- */
-/**
- * gst_byte_reader_peek_float32_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 32 bit big endian float without checking if there is enough
- * data available, but keep the current position.
- *
- * Returns: floating point value read
- */
-/**
- * gst_byte_reader_get_float64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 64 bit little endian float without checking if there is enough
- * data available and update the current position.
- *
- * Returns: double precision floating point value read
- */
-/**
- * gst_byte_reader_peek_float64_le_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 64 bit little endian float without checking if there is enough
- * data available, but keep the current position.
- *
- * Returns: double precision floating point value read
- */
-/**
- * gst_byte_reader_get_float64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 64 bit big endian float without checking if there is enough
- * data available and update the current position.
- *
- * Returns: double precision floating point value read
- */
-/**
- * gst_byte_reader_peek_float64_be_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Read a 64 bit big endian float without checking if there is enough
- * data available, but keep the current position.
- *
- * Returns: double precision floating point value read
- */
-
-gfloat gst_byte_reader_get_float32_le_unchecked (GstByteReader * reader);
-gfloat gst_byte_reader_get_float32_be_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_get_float64_le_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_get_float64_be_unchecked (GstByteReader * reader);
-
-gfloat gst_byte_reader_peek_float32_le_unchecked (GstByteReader * reader);
-gfloat gst_byte_reader_peek_float32_be_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_peek_float64_le_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_peek_float64_be_unchecked (GstByteReader * reader);
-
-/**
- * gst_byte_reader_peek_data_unchecked:
- * @reader: a #GstByteReader instance
- *
- * Returns: (transfer none): a constant pointer to the current data position
- */
-const guint8 * gst_byte_reader_peek_data_unchecked (const GstByteReader * reader);
-/**
- * gst_byte_reader_get_data_unchecked:
- * @reader: a #GstByteReader instance
- * @size: Size in bytes
- *
- * Returns a constant pointer to the current data position without checking
- * if at least @size bytes are left. Advances the current read position by
- * @size bytes.
- *
- * Returns: (transfer none) (array length=size): a constant pointer to the
- * current data position.
- */
-const guint8 * gst_byte_reader_get_data_unchecked (GstByteReader * reader, guint size);
-/**
- * gst_byte_reader_dup_data_unchecked:
- * @reader: a #GstByteReader instance
- * @size: Size in bytes
- *
- * Returns a newly-allocated copy of the data at the current data position
- * without checking if at least @size bytes are left. Advances the current read
- * position by @size bytes.
- *
- * Free-function: g_free
- *
- * Returns: (transfer full) (array length=size): a newly-allocated copy of the
- * data @size bytes in size. Free with g_free() when no longer needed.
- */
-guint8 * gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size);
-
diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c
deleted file mode 100644
index c0a16efe3a..0000000000
--- a/libs/gst/base/gstbytereader.c
+++ /dev/null
@@ -1,1301 +0,0 @@
-/* GStreamer byte reader
- *
- * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- * Copyright (C) 2009,2014 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define GST_BYTE_READER_DISABLE_INLINES
-#include "gstbytereader.h"
-
-#include "gst/glib-compat-private.h"
-#include <string.h>
-
-/**
- * SECTION:gstbytereader
- * @title: GstByteReader
- * @short_description: Reads different integer, string and floating point
- * types from a memory buffer
- * @symbols:
- * - gst_byte_reader_skip_unchecked
- * - gst_byte_reader_get_uint8_unchecked
- * - gst_byte_reader_peek_uint8_unchecked
- * - gst_byte_reader_get_int8_unchecked
- * - gst_byte_reader_peek_int8_unchecked
- * - gst_byte_reader_get_uint16_le_unchecked
- * - gst_byte_reader_get_uint16_be_unchecked
- * - gst_byte_reader_peek_uint16_le_unchecked
- * - gst_byte_reader_peek_uint16_be_unchecked
- * - gst_byte_reader_get_int16_le_unchecked
- * - gst_byte_reader_get_int16_be_unchecked
- * - gst_byte_reader_peek_int16_le_unchecked
- * - gst_byte_reader_peek_int16_be_unchecked
- * - gst_byte_reader_get_uint24_le_unchecked
- * - gst_byte_reader_get_uint24_be_unchecked
- * - gst_byte_reader_peek_uint24_le_unchecked
- * - gst_byte_reader_peek_uint24_be_unchecked
- * - gst_byte_reader_get_int24_le_unchecked
- * - gst_byte_reader_get_int24_be_unchecked
- * - gst_byte_reader_peek_int24_le_unchecked
- * - gst_byte_reader_peek_int24_be_unchecked
- * - gst_byte_reader_get_uint32_le_unchecked
- * - gst_byte_reader_get_uint32_be_unchecked
- * - gst_byte_reader_peek_uint32_le_unchecked
- * - gst_byte_reader_peek_uint32_be_unchecked
- * - gst_byte_reader_get_int32_le_unchecked
- * - gst_byte_reader_get_int32_be_unchecked
- * - gst_byte_reader_peek_int32_le_unchecked
- * - gst_byte_reader_peek_int32_be_unchecked
- * - gst_byte_reader_get_float32_le_unchecked
- * - gst_byte_reader_get_float32_be_unchecked
- * - gst_byte_reader_get_float64_le_unchecked
- * - gst_byte_reader_get_float64_be_unchecked
- * - gst_byte_reader_peek_float32_le_unchecked
- * - gst_byte_reader_peek_float32_be_unchecked
- * - gst_byte_reader_peek_float64_le_unchecked
- * - gst_byte_reader_peek_float64_be_unchecked
- * - gst_byte_reader_peek_data_unchecked
- * - gst_byte_reader_get_data_unchecked
- * - gst_byte_reader_dup_data_unchecked
- *
- * #GstByteReader provides a byte reader that can read different integer and
- * floating point types from a memory buffer. It provides functions for reading
- * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
- * and functions for reading little/big endian floating points numbers of
- * 32 and 64 bits. It also provides functions to read NUL-terminated strings
- * in various character encodings.
- */
-
-/**
- * gst_byte_reader_new: (skip)
- * @data: (in) (transfer none) (array length=size): data from which the
- * #GstByteReader should read
- * @size: Size of @data in bytes
- *
- * Create a new #GstByteReader instance, which will read from @data.
- *
- * Free-function: gst_byte_reader_free
- *
- * Returns: (transfer full): a new #GstByteReader instance
- */
-GstByteReader *
-gst_byte_reader_new (const guint8 * data, guint size)
-{
- GstByteReader *ret = g_slice_new0 (GstByteReader);
-
- ret->data = data;
- ret->size = size;
-
- return ret;
-}
-
-/**
- * gst_byte_reader_free:
- * @reader: (in) (transfer full): a #GstByteReader instance
- *
- * Frees a #GstByteReader instance, which was previously allocated by
- * gst_byte_reader_new().
- */
-void
-gst_byte_reader_free (GstByteReader * reader)
-{
- g_return_if_fail (reader != NULL);
-
- g_slice_free (GstByteReader, reader);
-}
-
-/**
- * gst_byte_reader_init:
- * @reader: a #GstByteReader instance
- * @data: (in) (transfer none) (array length=size): data from which
- * the #GstByteReader should read
- * @size: Size of @data in bytes
- *
- * Initializes a #GstByteReader instance to read from @data. This function
- * can be called on already initialized instances.
- */
-void
-gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
-{
- g_return_if_fail (reader != NULL);
-
- reader->data = data;
- reader->size = size;
- reader->byte = 0;
-}
-
-/**
- * gst_byte_reader_peek_sub_reader: (skip)
- * @reader: an existing and initialized #GstByteReader instance
- * @sub_reader: a #GstByteReader instance to initialize as sub-reader
- * @size: size of @sub_reader in bytes
- *
- * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
- * data from the current position of @reader. This is useful to read chunked
- * formats and make sure that one doesn't read beyond the size of the sub-chunk.
- *
- * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the
- * current position of @reader.
- *
- * Returns: FALSE on error or if @reader does not contain @size more bytes from
- * the current position, and otherwise TRUE
- *
- * Since: 1.6
- */
-gboolean
-gst_byte_reader_peek_sub_reader (GstByteReader * reader,
- GstByteReader * sub_reader, guint size)
-{
- return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
-}
-
-/**
- * gst_byte_reader_get_sub_reader: (skip)
- * @reader: an existing and initialized #GstByteReader instance
- * @sub_reader: a #GstByteReader instance to initialize as sub-reader
- * @size: size of @sub_reader in bytes
- *
- * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
- * data from the current position of @reader. This is useful to read chunked
- * formats and make sure that one doesn't read beyond the size of the sub-chunk.
- *
- * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the
- * position of @reader and moves it forward by @size bytes.
- *
- * Returns: FALSE on error or if @reader does not contain @size more bytes from
- * the current position, and otherwise TRUE
- *
- * Since: 1.6
- */
-gboolean
-gst_byte_reader_get_sub_reader (GstByteReader * reader,
- GstByteReader * sub_reader, guint size)
-{
- return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
-}
-
-/**
- * gst_byte_reader_set_pos:
- * @reader: a #GstByteReader instance
- * @pos: The new position in bytes
- *
- * Sets the new position of a #GstByteReader instance to @pos in bytes.
- *
- * Returns: %TRUE if the position could be set successfully, %FALSE
- * otherwise.
- */
-gboolean
-gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
-
- if (pos > reader->size)
- return FALSE;
-
- reader->byte = pos;
-
- return TRUE;
-}
-
-/**
- * gst_byte_reader_get_pos:
- * @reader: a #GstByteReader instance
- *
- * Returns the current position of a #GstByteReader instance in bytes.
- *
- * Returns: The current position of @reader in bytes.
- */
-guint
-gst_byte_reader_get_pos (const GstByteReader * reader)
-{
- return _gst_byte_reader_get_pos_inline (reader);
-}
-
-/**
- * gst_byte_reader_get_remaining:
- * @reader: a #GstByteReader instance
- *
- * Returns the remaining number of bytes of a #GstByteReader instance.
- *
- * Returns: The remaining number of bytes of @reader instance.
- */
-guint
-gst_byte_reader_get_remaining (const GstByteReader * reader)
-{
- return _gst_byte_reader_get_remaining_inline (reader);
-}
-
-/**
- * gst_byte_reader_get_size:
- * @reader: a #GstByteReader instance
- *
- * Returns the total number of bytes of a #GstByteReader instance.
- *
- * Returns: The total number of bytes of @reader instance.
- */
-guint
-gst_byte_reader_get_size (const GstByteReader * reader)
-{
- return _gst_byte_reader_get_size_inline (reader);
-}
-
-#define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline
-#define gst_byte_reader_get_size _gst_byte_reader_get_size_inline
-
-/**
- * gst_byte_reader_skip:
- * @reader: a #GstByteReader instance
- * @nbytes: the number of bytes to skip
- *
- * Skips @nbytes bytes of the #GstByteReader instance.
- *
- * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
-{
- return _gst_byte_reader_skip_inline (reader, nbytes);
-}
-
-/**
- * gst_byte_reader_get_uint8:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint8 to store the result
- *
- * Read an unsigned 8 bit integer into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int8:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint8 to store the result
- *
- * Read a signed 8 bit integer into @val and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint8:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint8 to store the result
- *
- * Read an unsigned 8 bit integer into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int8:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint8 to store the result
- *
- * Read a signed 8 bit integer into @val but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint16_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- *
- * Read an unsigned 16 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int16_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint16 to store the result
- *
- * Read a signed 16 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint16_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- *
- * Read an unsigned 16 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int16_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint16 to store the result
- *
- * Read a signed 16 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint16_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- *
- * Read an unsigned 16 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int16_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint16 to store the result
- *
- * Read a signed 16 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint16_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint16 to store the result
- *
- * Read an unsigned 16 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int16_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint16 to store the result
- *
- * Read a signed 16 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint24_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 24 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int24_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 24 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint24_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 24 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int24_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 24 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint24_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 24 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int24_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 24 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint24_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 24 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int24_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 24 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-
-/**
- * gst_byte_reader_get_uint32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 32 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 32 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 32 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 32 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 32 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 32 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint32 to store the result
- *
- * Read an unsigned 32 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint32 to store the result
- *
- * Read a signed 32 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- *
- * Read an unsigned 64 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint64 to store the result
- *
- * Read a signed 64 bit little endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- *
- * Read an unsigned 64 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint64 to store the result
- *
- * Read a signed 64 bit little endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_uint64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- *
- * Read an unsigned 64 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_int64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint64 to store the result
- *
- * Read a signed 64 bit big endian integer into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_uint64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #guint64 to store the result
- *
- * Read an unsigned 64 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_int64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gint64 to store the result
- *
- * Read a signed 64 bit big endian integer into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-#define GST_BYTE_READER_PEEK_GET(bits,type,name) \
-gboolean \
-gst_byte_reader_get_##name (GstByteReader * reader, type * val) \
-{ \
- return _gst_byte_reader_get_##name##_inline (reader, val); \
-} \
-\
-gboolean \
-gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \
-{ \
- return _gst_byte_reader_peek_##name##_inline (reader, val); \
-}
-
-/* *INDENT-OFF* */
-
-GST_BYTE_READER_PEEK_GET(8,guint8,uint8)
-GST_BYTE_READER_PEEK_GET(8,gint8,int8)
-
-GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
-GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
-GST_BYTE_READER_PEEK_GET(16,gint16,int16_le)
-GST_BYTE_READER_PEEK_GET(16,gint16,int16_be)
-
-GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
-GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
-GST_BYTE_READER_PEEK_GET(24,gint32,int24_le)
-GST_BYTE_READER_PEEK_GET(24,gint32,int24_be)
-
-GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
-GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
-GST_BYTE_READER_PEEK_GET(32,gint32,int32_le)
-GST_BYTE_READER_PEEK_GET(32,gint32,int32_be)
-
-GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
-GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
-GST_BYTE_READER_PEEK_GET(64,gint64,int64_le)
-GST_BYTE_READER_PEEK_GET(64,gint64,int64_be)
-
-/**
- * gst_byte_reader_get_float32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gfloat to store the result
- *
- * Read a 32 bit little endian floating point value into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_float32_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gfloat to store the result
- *
- * Read a 32 bit little endian floating point value into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_float32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gfloat to store the result
- *
- * Read a 32 bit big endian floating point value into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_float32_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gfloat to store the result
- *
- * Read a 32 bit big endian floating point value into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_float64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gdouble to store the result
- *
- * Read a 64 bit little endian floating point value into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_float64_le:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gdouble to store the result
- *
- * Read a 64 bit little endian floating point value into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_get_float64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gdouble to store the result
- *
- * Read a 64 bit big endian floating point value into @val
- * and update the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-/**
- * gst_byte_reader_peek_float64_be:
- * @reader: a #GstByteReader instance
- * @val: (out): Pointer to a #gdouble to store the result
- *
- * Read a 64 bit big endian floating point value into @val
- * but keep the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-
-GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
-GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
-GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
-GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
-
-/* *INDENT-ON* */
-
-/**
- * gst_byte_reader_get_data:
- * @reader: a #GstByteReader instance
- * @size: Size in bytes
- * @val: (out) (transfer none) (array length=size): address of a
- * #guint8 pointer variable in which to store the result
- *
- * Returns a constant pointer to the current data
- * position if at least @size bytes are left and
- * updates the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_get_data (GstByteReader * reader, guint size,
- const guint8 ** val)
-{
- return _gst_byte_reader_get_data_inline (reader, size, val);
-}
-
-/**
- * gst_byte_reader_peek_data:
- * @reader: a #GstByteReader instance
- * @size: Size in bytes
- * @val: (out) (transfer none) (array length=size): address of a
- * #guint8 pointer variable in which to store the result
- *
- * Returns a constant pointer to the current data
- * position if at least @size bytes are left and
- * keeps the current position.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_peek_data (const GstByteReader * reader, guint size,
- const guint8 ** val)
-{
- return _gst_byte_reader_peek_data_inline (reader, size, val);
-}
-
-/**
- * gst_byte_reader_dup_data:
- * @reader: a #GstByteReader instance
- * @size: Size in bytes
- * @val: (out) (transfer full) (array length=size): address of a
- * #guint8 pointer variable in which to store the result
- *
- * Free-function: g_free
- *
- * Returns a newly-allocated copy of the current data
- * position if at least @size bytes are left and
- * updates the current position. Free with g_free() when no longer needed.
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
-{
- return _gst_byte_reader_dup_data_inline (reader, size, val);
-}
-
-/* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
-static inline gint
-_scan_for_start_code (const guint8 * data, guint size)
-{
- guint8 *pdata = (guint8 *) data;
- guint8 *pend = (guint8 *) (data + size - 4);
-
- while (pdata <= pend) {
- if (pdata[2] > 1) {
- pdata += 3;
- } else if (pdata[1]) {
- pdata += 2;
- } else if (pdata[0] || pdata[2] != 1) {
- pdata++;
- } else {
- return (pdata - data);
- }
- }
-
- /* nothing found */
- return -1;
-}
-
-static inline guint
-_masked_scan_uint32_peek (const GstByteReader * reader,
- guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
-{
- const guint8 *data;
- guint32 state;
- guint i;
-
- g_return_val_if_fail (size > 0, -1);
- g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
- -1);
-
- /* we can't find the pattern with less than 4 bytes */
- if (G_UNLIKELY (size < 4))
- return -1;
-
- data = reader->data + reader->byte + offset;
-
- /* Handle special case found in MPEG and H264 */
- if ((pattern == 0x00000100) && (mask == 0xffffff00)) {
- gint ret = _scan_for_start_code (data, size);
-
- if (ret == -1)
- return ret;
-
- if (value != NULL)
- *value = (1 << 8) | data[ret + 3];
-
- return ret + offset;
- }
-
- /* set the state to something that does not match */
- state = ~pattern;
-
- /* now find data */
- for (i = 0; i < size; i++) {
- /* throw away one byte and move in the next byte */
- state = ((state << 8) | data[i]);
- if (G_UNLIKELY ((state & mask) == pattern)) {
- /* we have a match but we need to have skipped at
- * least 4 bytes to fill the state. */
- if (G_LIKELY (i >= 3)) {
- if (value)
- *value = state;
- return offset + i - 3;
- }
- }
- }
-
- /* nothing found */
- return -1;
-}
-
-
-/**
- * gst_byte_reader_masked_scan_uint32:
- * @reader: a #GstByteReader
- * @mask: mask to apply to data before matching against @pattern
- * @pattern: pattern to match (after mask is applied)
- * @offset: offset from which to start scanning, relative to the current
- * position
- * @size: number of bytes to scan from offset
- *
- * Scan for pattern @pattern with applied mask @mask in the byte reader data,
- * starting from offset @offset relative to the current position.
- *
- * The bytes in @pattern and @mask are interpreted left-to-right, regardless
- * of endianness. All four bytes of the pattern must be present in the
- * byte reader data for it to match, even if the first or last bytes are masked
- * out.
- *
- * It is an error to call this function without making sure that there is
- * enough data (offset+size bytes) in the byte reader.
- *
- * Returns: offset of the first match, or -1 if no match was found.
- *
- * Example:
- * |[
- * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
- *
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
- * // -> returns 0
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
- * // -> returns -1
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
- * // -> returns 1
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
- * // -> returns -1
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
- * // -> returns 0
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
- * // -> returns 2
- * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
- * // -> returns -1
- * ]|
- */
-guint
-gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
- guint32 pattern, guint offset, guint size)
-{
- return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
-}
-
-/**
- * gst_byte_reader_masked_scan_uint32_peek:
- * @reader: a #GstByteReader
- * @mask: mask to apply to data before matching against @pattern
- * @pattern: pattern to match (after mask is applied)
- * @offset: offset from which to start scanning, relative to the current
- * position
- * @size: number of bytes to scan from offset
- * @value: (out): pointer to uint32 to return matching data
- *
- * Scan for pattern @pattern with applied mask @mask in the byte reader data,
- * starting from offset @offset relative to the current position.
- *
- * The bytes in @pattern and @mask are interpreted left-to-right, regardless
- * of endianness. All four bytes of the pattern must be present in the
- * byte reader data for it to match, even if the first or last bytes are masked
- * out.
- *
- * It is an error to call this function without making sure that there is
- * enough data (offset+size bytes) in the byte reader.
- *
- * Returns: offset of the first match, or -1 if no match was found.
- *
- * Since: 1.6
- */
-guint
-gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
- guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
-{
- return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value);
-}
-
-#define GST_BYTE_READER_SCAN_STRING(bits) \
-static guint \
-gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \
-{ \
- guint len, off, max_len; \
- \
- max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
- \
- /* need at least a single NUL terminator */ \
- if (max_len < 1) \
- return 0; \
- \
- len = 0; \
- off = reader->byte; \
- /* endianness does not matter if we are looking for a NUL terminator */ \
- while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
- ++len; \
- off += sizeof (guint##bits); \
- /* have we reached the end without finding a NUL terminator? */ \
- if (len == max_len) \
- return 0; \
- } \
- /* return size in bytes including the NUL terminator (hence the +1) */ \
- return (len + 1) * sizeof (guint##bits); \
-}
-
-#define GST_READ_UINT8_LE GST_READ_UINT8
-GST_BYTE_READER_SCAN_STRING (8);
-#undef GST_READ_UINT8_LE
-GST_BYTE_READER_SCAN_STRING (16);
-GST_BYTE_READER_SCAN_STRING (32);
-
-#define GST_BYTE_READER_SKIP_STRING(bits) \
-gboolean \
-gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
-{ \
- guint size; /* size in bytes including the terminator */ \
- \
- g_return_val_if_fail (reader != NULL, FALSE); \
- \
- size = gst_byte_reader_scan_string_utf##bits (reader); \
- reader->byte += size; \
- return (size > 0); \
-}
-
-/**
- * gst_byte_reader_skip_string:
- * @reader: a #GstByteReader instance
- *
- * Skips a NUL-terminated string in the #GstByteReader instance, advancing
- * the current position to the byte after the string. This will work for
- * any NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-/**
- * gst_byte_reader_skip_string_utf8:
- * @reader: a #GstByteReader instance
- *
- * Skips a NUL-terminated string in the #GstByteReader instance, advancing
- * the current position to the byte after the string. This will work for
- * any NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-GST_BYTE_READER_SKIP_STRING (8);
-
-/**
- * gst_byte_reader_skip_string_utf16:
- * @reader: a #GstByteReader instance
- *
- * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
- * advancing the current position to the byte after the string.
- *
- * No input checking for valid UTF-16 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-GST_BYTE_READER_SKIP_STRING (16);
-
-/**
- * gst_byte_reader_skip_string_utf32:
- * @reader: a #GstByteReader instance
- *
- * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
- * advancing the current position to the byte after the string.
- *
- * No input checking for valid UTF-32 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-GST_BYTE_READER_SKIP_STRING (32);
-
-/**
- * gst_byte_reader_peek_string:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer variable in which to store the result
- *
- * Returns a constant pointer to the current data position if there is
- * a NUL-terminated string in the data (this could be just a NUL terminator).
- * The current position will be maintained. This will work for any
- * NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-/**
- * gst_byte_reader_peek_string_utf8:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer variable in which to store the result
- *
- * Returns a constant pointer to the current data position if there is
- * a NUL-terminated string in the data (this could be just a NUL terminator).
- * The current position will be maintained. This will work for any
- * NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc.
- *
- * No input checking for valid UTF-8 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
- const gchar ** str)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (str != NULL, FALSE);
-
- if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
- *str = (const gchar *) (reader->data + reader->byte);
- } else {
- *str = NULL;
- }
- return (*str != NULL);
-}
-
-/**
- * gst_byte_reader_get_string_utf8:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer variable in which to store the result
- *
- * Returns a constant pointer to the current data position if there is
- * a NUL-terminated string in the data (this could be just a NUL terminator),
- * advancing the current position to the byte after the string. This will work
- * for any NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc.
- *
- * No input checking for valid UTF-8 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be found, %FALSE otherwise.
- */
-gboolean
-gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
-{
- guint size; /* size in bytes including the terminator */
-
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (str != NULL, FALSE);
-
- size = gst_byte_reader_scan_string_utf8 (reader);
- if (size == 0) {
- *str = NULL;
- return FALSE;
- }
-
- *str = (const gchar *) (reader->data + reader->byte);
- reader->byte += size;
- return TRUE;
-}
-
-#define GST_BYTE_READER_DUP_STRING(bits,type) \
-gboolean \
-gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
-{ \
- guint size; /* size in bytes including the terminator */ \
- \
- g_return_val_if_fail (reader != NULL, FALSE); \
- g_return_val_if_fail (str != NULL, FALSE); \
- \
- size = gst_byte_reader_scan_string_utf##bits (reader); \
- if (size == 0) { \
- *str = NULL; \
- return FALSE; \
- } \
- *str = g_memdup2 (reader->data + reader->byte, size); \
- reader->byte += size; \
- return TRUE; \
-}
-
-/**
- * gst_byte_reader_dup_string_utf8:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #gchar pointer variable in which to store the result
- *
- * Free-function: g_free
- *
- * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
- * advancing the current position to the byte after the string. This will work
- * for any NUL-terminated string with a character width of 8 bits, so ASCII,
- * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
- * string put into @str must be freed with g_free() when no longer needed.
- */
-GST_BYTE_READER_DUP_STRING (8, gchar);
-
-/**
- * gst_byte_reader_dup_string_utf16:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #guint16 pointer variable in which to store the result
- *
- * Free-function: g_free
- *
- * Returns a newly-allocated copy of the current data position if there is
- * a NUL-terminated UTF-16 string in the data (this could be an empty string
- * as well), and advances the current position.
- *
- * No input checking for valid UTF-16 is done. This function is endianness
- * agnostic - you should not assume the UTF-16 characters are in host
- * endianness.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Note: there is no peek or get variant of this function to ensure correct
- * byte alignment of the UTF-16 string.
- *
- * Returns: %TRUE if a string could be read, %FALSE otherwise. The
- * string put into @str must be freed with g_free() when no longer needed.
- */
-GST_BYTE_READER_DUP_STRING (16, guint16);
-
-/**
- * gst_byte_reader_dup_string_utf32:
- * @reader: a #GstByteReader instance
- * @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #guint32 pointer variable in which to store the result
- *
- * Free-function: g_free
- *
- * Returns a newly-allocated copy of the current data position if there is
- * a NUL-terminated UTF-32 string in the data (this could be an empty string
- * as well), and advances the current position.
- *
- * No input checking for valid UTF-32 is done. This function is endianness
- * agnostic - you should not assume the UTF-32 characters are in host
- * endianness.
- *
- * This function will fail if no NUL-terminator was found in in the data.
- *
- * Note: there is no peek or get variant of this function to ensure correct
- * byte alignment of the UTF-32 string.
- *
- * Returns: %TRUE if a string could be read, %FALSE otherwise. The
- * string put into @str must be freed with g_free() when no longer needed.
- */
-GST_BYTE_READER_DUP_STRING (32, guint32);
diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h
deleted file mode 100644
index 2130a8a008..0000000000
--- a/libs/gst/base/gstbytereader.h
+++ /dev/null
@@ -1,684 +0,0 @@
-/* GStreamer byte reader
- *
- * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BYTE_READER_H__
-#define __GST_BYTE_READER_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_BYTE_READER(reader) ((GstByteReader *) (reader))
-
-/**
- * GstByteReader:
- * @data: (array length=size): Data from which the bit reader will
- * read
- * @size: Size of @data in bytes
- * @byte: Current byte position
- *
- * A byte reader instance.
- */
-typedef struct {
- const guint8 *data;
- guint size;
-
- guint byte; /* Byte position */
-
- /* < private > */
- gpointer _gst_reserved[GST_PADDING];
-} GstByteReader;
-
-GST_BASE_API
-GstByteReader * gst_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_byte_reader_free (GstByteReader *reader);
-
-GST_BASE_API
-void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_sub_reader (GstByteReader * reader,
- GstByteReader * sub_reader,
- guint size);
-GST_BASE_API
-gboolean gst_byte_reader_get_sub_reader (GstByteReader * reader,
- GstByteReader * sub_reader,
- guint size);
-GST_BASE_API
-gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos);
-
-GST_BASE_API
-guint gst_byte_reader_get_pos (const GstByteReader *reader);
-
-GST_BASE_API
-guint gst_byte_reader_get_remaining (const GstByteReader *reader);
-
-GST_BASE_API
-guint gst_byte_reader_get_size (const GstByteReader *reader);
-
-GST_BASE_API
-gboolean gst_byte_reader_skip (GstByteReader *reader, guint nbytes);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint8 (GstByteReader *reader, guint8 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int8 (GstByteReader *reader, gint8 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint16_le (GstByteReader *reader, guint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int16_le (GstByteReader *reader, gint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint16_be (GstByteReader *reader, guint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int16_be (GstByteReader *reader, gint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint24_le (GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int24_le (GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint24_be (GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int24_be (GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint32_le (GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int32_le (GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint32_be (GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int32_be (GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint64_le (GstByteReader *reader, guint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int64_le (GstByteReader *reader, gint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_uint64_be (GstByteReader *reader, guint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_int64_be (GstByteReader *reader, gint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint8 (const GstByteReader *reader, guint8 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int8 (const GstByteReader *reader, gint8 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint16_le (const GstByteReader *reader, guint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int16_le (const GstByteReader *reader, gint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint16_be (const GstByteReader *reader, guint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int16_be (const GstByteReader *reader, gint16 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint24_le (const GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int24_le (const GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint24_be (const GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int24_be (const GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint32_le (const GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int32_le (const GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint32_be (const GstByteReader *reader, guint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int32_be (const GstByteReader *reader, gint32 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint64_le (const GstByteReader *reader, guint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int64_le (const GstByteReader *reader, gint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_uint64_be (const GstByteReader *reader, guint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_int64_be (const GstByteReader *reader, gint64 *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_float32_le (GstByteReader *reader, gfloat *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_float32_be (GstByteReader *reader, gfloat *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_float64_le (GstByteReader *reader, gdouble *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_float64_be (GstByteReader *reader, gdouble *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_float32_le (const GstByteReader *reader, gfloat *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_float32_be (const GstByteReader *reader, gfloat *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_float64_le (const GstByteReader *reader, gdouble *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_float64_be (const GstByteReader *reader, gdouble *val);
-
-GST_BASE_API
-gboolean gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val);
-
-GST_BASE_API
-gboolean gst_byte_reader_get_data (GstByteReader * reader, guint size, const guint8 ** val);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_data (const GstByteReader * reader, guint size, const guint8 ** val);
-
-#define gst_byte_reader_dup_string(reader,str) \
- gst_byte_reader_dup_string_utf8(reader,str)
-
-GST_BASE_API
-gboolean gst_byte_reader_dup_string_utf8 (GstByteReader * reader, gchar ** str);
-
-GST_BASE_API
-gboolean gst_byte_reader_dup_string_utf16 (GstByteReader * reader, guint16 ** str);
-
-GST_BASE_API
-gboolean gst_byte_reader_dup_string_utf32 (GstByteReader * reader, guint32 ** str);
-
-#define gst_byte_reader_skip_string(reader) \
- gst_byte_reader_skip_string_utf8(reader)
-
-GST_BASE_API
-gboolean gst_byte_reader_skip_string_utf8 (GstByteReader * reader);
-
-GST_BASE_API
-gboolean gst_byte_reader_skip_string_utf16 (GstByteReader * reader);
-
-GST_BASE_API
-gboolean gst_byte_reader_skip_string_utf32 (GstByteReader * reader);
-
-#define gst_byte_reader_get_string(reader,str) \
- gst_byte_reader_get_string_utf8(reader,str)
-
-#define gst_byte_reader_peek_string(reader,str) \
- gst_byte_reader_peek_string_utf8(reader,str)
-
-GST_BASE_API
-gboolean gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str);
-
-GST_BASE_API
-gboolean gst_byte_reader_peek_string_utf8 (const GstByteReader * reader, const gchar ** str);
-
-GST_BASE_API
-guint gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader,
- guint32 mask,
- guint32 pattern,
- guint offset,
- guint size);
-GST_BASE_API
-guint gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
- guint32 mask,
- guint32 pattern,
- guint offset,
- guint size,
- guint32 * value);
-
-/**
- * GST_BYTE_READER_INIT:
- * @data: Data from which the #GstByteReader should read
- * @size: Size of @data in bytes
- *
- * A #GstByteReader must be initialized with this macro, before it can be
- * used. This macro can used be to initialize a variable, but it cannot
- * be assigned to a variable. In that case you have to use
- * gst_byte_reader_init().
- */
-#define GST_BYTE_READER_INIT(data, size) {data, size, 0}
-
-/* unchecked variants */
-static inline void
-gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes)
-{
- reader->byte += nbytes;
-}
-
-#define __GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(bits,type,lower,upper,adj) \
-\
-static inline type \
-gst_byte_reader_peek_##lower##_unchecked (const GstByteReader * reader) \
-{ \
- type val = (type) GST_READ_##upper (reader->data + reader->byte); \
- adj \
- return val; \
-} \
-\
-static inline type \
-gst_byte_reader_get_##lower##_unchecked (GstByteReader * reader) \
-{ \
- type val = gst_byte_reader_peek_##lower##_unchecked (reader); \
- reader->byte += bits / 8; \
- return val; \
-}
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,guint8,uint8,UINT8,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,gint8,int8,UINT8,/* */)
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_le,UINT16_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_be,UINT16_BE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_le,UINT16_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_be,UINT16_BE,/* */)
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_le,UINT32_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_be,UINT32_BE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_le,UINT32_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_be,UINT32_BE,/* */)
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_le,UINT24_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_be,UINT24_BE,/* */)
-
-/* fix up the sign for 24-bit signed ints stored in 32-bit signed ints */
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_le,UINT24_LE,
- if (val & 0x00800000) val |= 0xff000000;)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_be,UINT24_BE,
- if (val & 0x00800000) val |= 0xff000000;)
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_le,UINT64_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_be,UINT64_BE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_le,UINT64_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_be,UINT64_BE,/* */)
-
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_le,FLOAT_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_be,FLOAT_BE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_le,DOUBLE_LE,/* */)
-__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_be,DOUBLE_BE,/* */)
-
-#undef __GET_PEEK_BITS_UNCHECKED
-
-static inline const guint8 *
-gst_byte_reader_peek_data_unchecked (const GstByteReader * reader)
-{
- return (const guint8 *) (reader->data + reader->byte);
-}
-
-static inline const guint8 *
-gst_byte_reader_get_data_unchecked (GstByteReader * reader, guint size)
-{
- const guint8 *data;
-
- data = gst_byte_reader_peek_data_unchecked (reader);
- gst_byte_reader_skip_unchecked (reader, size);
- return data;
-}
-
-static inline guint8 *
-gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size)
-{
- gconstpointer data = gst_byte_reader_get_data_unchecked (reader, size);
- guint8 *dup_data = (guint8 *) g_malloc (size);
-
- memcpy (dup_data, data, size);
- return dup_data;
-}
-
-/* Unchecked variants that should not be used */
-static inline guint
-_gst_byte_reader_get_pos_unchecked (const GstByteReader * reader)
-{
- return reader->byte;
-}
-
-static inline guint
-_gst_byte_reader_get_remaining_unchecked (const GstByteReader * reader)
-{
- return reader->size - reader->byte;
-}
-
-static inline guint
-_gst_byte_reader_get_size_unchecked (const GstByteReader * reader)
-{
- return reader->size;
-}
-
-/* inlined variants (do not use directly) */
-
-static inline guint
-_gst_byte_reader_get_remaining_inline (const GstByteReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_byte_reader_get_remaining_unchecked (reader);
-}
-
-static inline guint
-_gst_byte_reader_get_size_inline (const GstByteReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_byte_reader_get_size_unchecked (reader);
-}
-
-#define __GST_BYTE_READER_GET_PEEK_BITS_INLINE(bits,type,name) \
-\
-static inline gboolean \
-_gst_byte_reader_peek_##name##_inline (const GstByteReader * reader, type * val) \
-{ \
- g_return_val_if_fail (reader != NULL, FALSE); \
- g_return_val_if_fail (val != NULL, FALSE); \
- \
- if (_gst_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \
- return FALSE; \
-\
- *val = gst_byte_reader_peek_##name##_unchecked (reader); \
- return TRUE; \
-} \
-\
-static inline gboolean \
-_gst_byte_reader_get_##name##_inline (GstByteReader * reader, type * val) \
-{ \
- g_return_val_if_fail (reader != NULL, FALSE); \
- g_return_val_if_fail (val != NULL, FALSE); \
- \
- if (_gst_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \
- return FALSE; \
-\
- *val = gst_byte_reader_get_##name##_unchecked (reader); \
- return TRUE; \
-}
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(8,guint8,uint8)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(8,gint8,int8)
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_be)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_be)
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_be)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_be)
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_be)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_be)
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_be)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_be)
-
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_be)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_le)
-__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_be)
-
-#undef __GST_BYTE_READER_GET_PEEK_BITS_INLINE
-
-#ifndef GST_BYTE_READER_DISABLE_INLINES
-
-#define gst_byte_reader_init(reader,data,size) \
- _gst_byte_reader_init_inline(reader,data,size)
-
-#define gst_byte_reader_get_remaining(reader) \
- _gst_byte_reader_get_remaining_inline(reader)
-
-#define gst_byte_reader_get_size(reader) \
- _gst_byte_reader_get_size_inline(reader)
-
-#define gst_byte_reader_get_pos(reader) \
- _gst_byte_reader_get_pos_inline(reader)
-
-/* we use defines here so we can add the G_LIKELY() */
-#define gst_byte_reader_get_uint8(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint8_inline(reader,val))
-#define gst_byte_reader_get_int8(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int8_inline(reader,val))
-#define gst_byte_reader_get_uint16_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint16_le_inline(reader,val))
-#define gst_byte_reader_get_int16_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int16_le_inline(reader,val))
-#define gst_byte_reader_get_uint16_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint16_be_inline(reader,val))
-#define gst_byte_reader_get_int16_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int16_be_inline(reader,val))
-#define gst_byte_reader_get_uint24_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint24_le_inline(reader,val))
-#define gst_byte_reader_get_int24_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int24_le_inline(reader,val))
-#define gst_byte_reader_get_uint24_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint24_be_inline(reader,val))
-#define gst_byte_reader_get_int24_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int24_be_inline(reader,val))
-#define gst_byte_reader_get_uint32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint32_le_inline(reader,val))
-#define gst_byte_reader_get_int32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int32_le_inline(reader,val))
-#define gst_byte_reader_get_uint32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint32_be_inline(reader,val))
-#define gst_byte_reader_get_int32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int32_be_inline(reader,val))
-#define gst_byte_reader_get_uint64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint64_le_inline(reader,val))
-#define gst_byte_reader_get_int64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int64_le_inline(reader,val))
-#define gst_byte_reader_get_uint64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_uint64_be_inline(reader,val))
-#define gst_byte_reader_get_int64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_int64_be_inline(reader,val))
-
-#define gst_byte_reader_peek_uint8(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint8_inline(reader,val))
-#define gst_byte_reader_peek_int8(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int8_inline(reader,val))
-#define gst_byte_reader_peek_uint16_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint16_le_inline(reader,val))
-#define gst_byte_reader_peek_int16_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int16_le_inline(reader,val))
-#define gst_byte_reader_peek_uint16_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint16_be_inline(reader,val))
-#define gst_byte_reader_peek_int16_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int16_be_inline(reader,val))
-#define gst_byte_reader_peek_uint24_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint24_le_inline(reader,val))
-#define gst_byte_reader_peek_int24_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int24_le_inline(reader,val))
-#define gst_byte_reader_peek_uint24_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint24_be_inline(reader,val))
-#define gst_byte_reader_peek_int24_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int24_be_inline(reader,val))
-#define gst_byte_reader_peek_uint32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint32_le_inline(reader,val))
-#define gst_byte_reader_peek_int32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int32_le_inline(reader,val))
-#define gst_byte_reader_peek_uint32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint32_be_inline(reader,val))
-#define gst_byte_reader_peek_int32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int32_be_inline(reader,val))
-#define gst_byte_reader_peek_uint64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint64_le_inline(reader,val))
-#define gst_byte_reader_peek_int64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int64_le_inline(reader,val))
-#define gst_byte_reader_peek_uint64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_uint64_be_inline(reader,val))
-#define gst_byte_reader_peek_int64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_int64_be_inline(reader,val))
-
-#define gst_byte_reader_get_float32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_float32_le_inline(reader,val))
-#define gst_byte_reader_get_float32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_float32_be_inline(reader,val))
-#define gst_byte_reader_get_float64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_get_float64_le_inline(reader,val))
-#define gst_byte_reader_get_float64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_get_float64_be_inline(reader,val))
-#define gst_byte_reader_peek_float32_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_float32_le_inline(reader,val))
-#define gst_byte_reader_peek_float32_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_float32_be_inline(reader,val))
-#define gst_byte_reader_peek_float64_le(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_float64_le_inline(reader,val))
-#define gst_byte_reader_peek_float64_be(reader,val) \
- G_LIKELY(_gst_byte_reader_peek_float64_be_inline(reader,val))
-
-#endif /* GST_BYTE_READER_DISABLE_INLINES */
-
-static inline void
-_gst_byte_reader_init_inline (GstByteReader * reader, const guint8 * data, guint size)
-{
- g_return_if_fail (reader != NULL);
-
- reader->data = data;
- reader->size = size;
- reader->byte = 0;
-}
-
-static inline gboolean
-_gst_byte_reader_peek_sub_reader_inline (GstByteReader * reader,
- GstByteReader * sub_reader, guint size)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (sub_reader != NULL, FALSE);
-
- if (_gst_byte_reader_get_remaining_unchecked (reader) < size)
- return FALSE;
-
- sub_reader->data = reader->data + reader->byte;
- sub_reader->byte = 0;
- sub_reader->size = size;
- return TRUE;
-}
-
-static inline gboolean
-_gst_byte_reader_get_sub_reader_inline (GstByteReader * reader,
- GstByteReader * sub_reader, guint size)
-{
- if (!_gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size))
- return FALSE;
- gst_byte_reader_skip_unchecked (reader, size);
- return TRUE;
-}
-
-static inline gboolean
-_gst_byte_reader_dup_data_inline (GstByteReader * reader, guint size, guint8 ** val)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (val != NULL, FALSE);
-
- if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size))
- return FALSE;
-
- *val = gst_byte_reader_dup_data_unchecked (reader, size);
- return TRUE;
-}
-
-static inline gboolean
-_gst_byte_reader_get_data_inline (GstByteReader * reader, guint size, const guint8 ** val)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (val != NULL, FALSE);
-
- if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size))
- return FALSE;
-
- *val = gst_byte_reader_get_data_unchecked (reader, size);
- return TRUE;
-}
-
-static inline gboolean
-_gst_byte_reader_peek_data_inline (const GstByteReader * reader, guint size, const guint8 ** val)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
- g_return_val_if_fail (val != NULL, FALSE);
-
- if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size))
- return FALSE;
-
- *val = gst_byte_reader_peek_data_unchecked (reader);
- return TRUE;
-}
-
-static inline guint
-_gst_byte_reader_get_pos_inline (const GstByteReader * reader)
-{
- g_return_val_if_fail (reader != NULL, 0);
-
- return _gst_byte_reader_get_pos_unchecked (reader);
-}
-
-static inline gboolean
-_gst_byte_reader_skip_inline (GstByteReader * reader, guint nbytes)
-{
- g_return_val_if_fail (reader != NULL, FALSE);
-
- if (G_UNLIKELY (_gst_byte_reader_get_remaining_unchecked (reader) < nbytes))
- return FALSE;
-
- reader->byte += nbytes;
- return TRUE;
-}
-
-#ifndef GST_BYTE_READER_DISABLE_INLINES
-
-#define gst_byte_reader_dup_data(reader,size,val) \
- G_LIKELY(_gst_byte_reader_dup_data_inline(reader,size,val))
-#define gst_byte_reader_get_data(reader,size,val) \
- G_LIKELY(_gst_byte_reader_get_data_inline(reader,size,val))
-#define gst_byte_reader_peek_data(reader,size,val) \
- G_LIKELY(_gst_byte_reader_peek_data_inline(reader,size,val))
-#define gst_byte_reader_skip(reader,nbytes) \
- G_LIKELY(_gst_byte_reader_skip_inline(reader,nbytes))
-
-#endif /* GST_BYTE_READER_DISABLE_INLINES */
-
-G_END_DECLS
-
-#endif /* __GST_BYTE_READER_H__ */
diff --git a/libs/gst/base/gstbytewriter-docs.h b/libs/gst/base/gstbytewriter-docs.h
deleted file mode 100644
index 3cc5962d41..0000000000
--- a/libs/gst/base/gstbytewriter-docs.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/* GStreamer byte writer dummy header for gtk-doc
- * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* This header is not installed, it just contains stuff for gtk-doc to parse,
- * in particular docs and some dummy function declarations for the static
- * inline functions we generate via macros in gstbitreader.h.
- */
-
-#error "This header should never be included in code, it is only for gtk-doc"
-
-/**
- * gst_byte_writer_put_uint8_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned 8 bit integer to @writer without checking if there
- * is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint8_unchecked (GstByteWriter *writer, guint8 val);
-
-/**
- * gst_byte_writer_put_uint16_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 16 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint16_be_unchecked (GstByteWriter *writer, guint16 val);
-
-/**
- * gst_byte_writer_put_uint24_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 24 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint24_be_unchecked (GstByteWriter *writer, guint32 val);
-
-/**
- * gst_byte_writer_put_uint32_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 32 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint32_be_unchecked (GstByteWriter *writer, guint32 val);
-
-/**
- * gst_byte_writer_put_uint64_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 64 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint64_be_unchecked (GstByteWriter *writer, guint64 val);
-
-/**
- * gst_byte_writer_put_uint16_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 16 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint16_le_unchecked (GstByteWriter *writer, guint16 val);
-
-/**
- * gst_byte_writer_put_uint24_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 24 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint24_le_unchecked (GstByteWriter *writer, guint32 val);
-
-/**
- * gst_byte_writer_put_uint32_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 32 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint32_le_unchecked (GstByteWriter *writer, guint32 val);
-
-/**
- * gst_byte_writer_put_uint64_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 64 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_uint64_le_unchecked (GstByteWriter *writer, guint64 val);
-
-/**
- * gst_byte_writer_put_int8:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed 8 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int8_unchecked (GstByteWriter *writer, gint8 val);
-
-/**
- * gst_byte_writer_put_int16_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 16 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int16_be_unchecked (GstByteWriter *writer, gint16 val);
-
-/**
- * gst_byte_writer_put_int24_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 24 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int24_be_unchecked (GstByteWriter *writer, gint32 val);
-
-/**
- * gst_byte_writer_put_int32_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 32 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int32_be_unchecked (GstByteWriter *writer, gint32 val);
-
-/**
- * gst_byte_writer_put_int64_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 64 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int64_be_unchecked (GstByteWriter *writer, gint64 val);
-
-/**
- * gst_byte_writer_put_int16_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 16 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int16_le_unchecked (GstByteWriter *writer, gint16 val);
-
-/**
- * gst_byte_writer_put_int24_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 24 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int24_le_unchecked (GstByteWriter *writer, gint32 val);
-
-/**
- * gst_byte_writer_put_int32_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 32 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int32_le_unchecked (GstByteWriter *writer, gint32 val);
-
-/**
- * gst_byte_writer_put_int64_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 64 bit integer to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_int64_le_unchecked (GstByteWriter *writer, gint64 val);
-
-/**
- * gst_byte_writer_put_float32_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a big endian 32 bit float to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_float32_be_unchecked (GstByteWriter *writer, gfloat val);
-
-/**
- * gst_byte_writer_put_float64_be_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a big endian 64 bit float to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_float64_be_unchecked (GstByteWriter *writer, gdouble val);
-
-/**
- * gst_byte_writer_put_float32_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a little endian 32 bit float to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_float32_le_unchecked (GstByteWriter *writer, gfloat val);
-
-/**
- * gst_byte_writer_put_float64_le_unchecked:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a little endian 64 bit float to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_float64_le_unchecked (GstByteWriter *writer, gdouble val);
-
-/**
- * gst_byte_writer_put_data_unchecked:
- * @writer: #GstByteWriter instance
- * @data: (in) (transfer none) (array length=size): Data to write
- * @size: Size of @data in bytes
- *
- * Writes @size bytes of @data to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_put_data_unchecked (GstByteWriter *writer, const guint8 *data, guint size);
-
-/**
- * gst_byte_writer_fill_unchecked:
- * @writer: #GstByteWriter instance
- * @value: Value to be written
- * @size: Number of bytes to be written
-
- *
- * Writes @size bytes containing @value to @writer without
- * checking if there is enough free space available in the byte writer.
- */
-void gst_byte_writer_fill_unchecked (GstByteWriter *writer, guint8 value, guint size);
-
diff --git a/libs/gst/base/gstbytewriter.c b/libs/gst/base/gstbytewriter.c
deleted file mode 100644
index aec10932e4..0000000000
--- a/libs/gst/base/gstbytewriter.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/* GStreamer byte writer
- *
- * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define GST_BYTE_WRITER_DISABLE_INLINES
-#include "gstbytewriter.h"
-
-#include "gst/glib-compat-private.h"
-
-/**
- * SECTION:gstbytewriter
- * @title: GstByteWriter
- * @short_description: Writes different integer, string and floating point
- * types to a memory buffer and allows reading
- * @symbols:
- * - gst_byte_writer_put_uint8_unchecked
- * - gst_byte_writer_put_uint16_be_unchecked
- * - gst_byte_writer_put_uint24_be_unchecked
- * - gst_byte_writer_put_uint32_be_unchecked
- * - gst_byte_writer_put_uint64_be_unchecked
- * - gst_byte_writer_put_uint16_le_unchecked
- * - gst_byte_writer_put_uint24_le_unchecked
- * - gst_byte_writer_put_uint32_le_unchecked
- * - gst_byte_writer_put_uint64_le_unchecked
- * - gst_byte_writer_put_int8_unchecked
- * - gst_byte_writer_put_int16_be_unchecked
- * - gst_byte_writer_put_int24_be_unchecked
- * - gst_byte_writer_put_int32_be_unchecked
- * - gst_byte_writer_put_int64_be_unchecked
- * - gst_byte_writer_put_int16_le_unchecked
- * - gst_byte_writer_put_int24_le_unchecked
- * - gst_byte_writer_put_int32_le_unchecked
- * - gst_byte_writer_put_int64_le_unchecked
- * - gst_byte_writer_put_float32_be_unchecked
- * - gst_byte_writer_put_float64_be_unchecked
- * - gst_byte_writer_put_float32_le_unchecked
- * - gst_byte_writer_put_float64_le_unchecked
- * - gst_byte_writer_put_data_unchecked
- * - gst_byte_writer_fill_unchecked
- *
- * #GstByteWriter provides a byte writer and reader that can write/read different
- * integer and floating point types to/from a memory buffer. It provides functions
- * for writing/reading signed/unsigned, little/big endian integers of 8, 16, 24,
- * 32 and 64 bits and functions for reading little/big endian floating points numbers of
- * 32 and 64 bits. It also provides functions to write/read NUL-terminated strings
- * in various character encodings.
- */
-
-/**
- * gst_byte_writer_new: (skip)
- *
- * Creates a new, empty #GstByteWriter instance
- *
- * Free-function: gst_byte_writer_free
- *
- * Returns: (transfer full): a new, empty #GstByteWriter instance
- */
-GstByteWriter *
-gst_byte_writer_new (void)
-{
- GstByteWriter *ret = g_slice_new0 (GstByteWriter);
-
- ret->owned = TRUE;
- return ret;
-}
-
-/**
- * gst_byte_writer_new_with_size: (skip)
- * @size: Initial size of data
- * @fixed: If %TRUE the data can't be reallocated
- *
- * Creates a new #GstByteWriter instance with the given
- * initial data size.
- *
- * Free-function: gst_byte_writer_free
- *
- * Returns: (transfer full): a new #GstByteWriter instance
- */
-GstByteWriter *
-gst_byte_writer_new_with_size (guint size, gboolean fixed)
-{
- GstByteWriter *ret = gst_byte_writer_new ();
-
- ret->alloc_size = size;
- ret->parent.data = g_malloc (ret->alloc_size);
- ret->fixed = fixed;
- ret->owned = TRUE;
-
- return ret;
-}
-
-/**
- * gst_byte_writer_new_with_data: (skip)
- * @data: Memory area for writing
- * @size: Size of @data in bytes
- * @initialized: If %TRUE the complete data can be read from the beginning
- *
- * Creates a new #GstByteWriter instance with the given
- * memory area. If @initialized is %TRUE it is possible to
- * read @size bytes from the #GstByteWriter from the beginning.
- *
- * Free-function: gst_byte_writer_free
- *
- * Returns: (transfer full): a new #GstByteWriter instance
- */
-GstByteWriter *
-gst_byte_writer_new_with_data (guint8 * data, guint size, gboolean initialized)
-{
- GstByteWriter *ret = gst_byte_writer_new ();
-
- ret->parent.data = data;
- ret->parent.size = (initialized) ? size : 0;
- ret->alloc_size = size;
- ret->fixed = TRUE;
- ret->owned = FALSE;
-
- return ret;
-}
-
-/**
- * gst_byte_writer_init:
- * @writer: #GstByteWriter instance
- *
- * Initializes @writer to an empty instance
- */
-void
-gst_byte_writer_init (GstByteWriter * writer)
-{
- g_return_if_fail (writer != NULL);
-
- memset (writer, 0, sizeof (GstByteWriter));
-
- writer->owned = TRUE;
-}
-
-/**
- * gst_byte_writer_init_with_size:
- * @writer: #GstByteWriter instance
- * @size: Initial size of data
- * @fixed: If %TRUE the data can't be reallocated
- *
- * Initializes @writer with the given initial data size.
- */
-void
-gst_byte_writer_init_with_size (GstByteWriter * writer, guint size,
- gboolean fixed)
-{
- g_return_if_fail (writer != NULL);
-
- gst_byte_writer_init (writer);
-
- writer->parent.data = g_malloc (size);
- writer->alloc_size = size;
- writer->fixed = fixed;
- writer->owned = TRUE;
-}
-
-/**
- * gst_byte_writer_init_with_data:
- * @writer: #GstByteWriter instance
- * @data: (array length=size) (transfer none): Memory area for writing
- * @size: Size of @data in bytes
- * @initialized: If %TRUE the complete data can be read from the beginning
- *
- * Initializes @writer with the given
- * memory area. If @initialized is %TRUE it is possible to
- * read @size bytes from the #GstByteWriter from the beginning.
- */
-void
-gst_byte_writer_init_with_data (GstByteWriter * writer, guint8 * data,
- guint size, gboolean initialized)
-{
- g_return_if_fail (writer != NULL);
-
- gst_byte_writer_init (writer);
-
- writer->parent.data = data;
- writer->parent.size = (initialized) ? size : 0;
- writer->alloc_size = size;
- writer->fixed = TRUE;
- writer->owned = FALSE;
-}
-
-/**
- * gst_byte_writer_reset:
- * @writer: #GstByteWriter instance
- *
- * Resets @writer and frees the data if it's
- * owned by @writer.
- */
-void
-gst_byte_writer_reset (GstByteWriter * writer)
-{
- g_return_if_fail (writer != NULL);
-
- if (writer->owned)
- g_free ((guint8 *) writer->parent.data);
- memset (writer, 0, sizeof (GstByteWriter));
-}
-
-/**
- * gst_byte_writer_reset_and_get_data:
- * @writer: #GstByteWriter instance
- *
- * Resets @writer and returns the current data.
- *
- * Free-function: g_free
- *
- * Returns: (array) (transfer full): the current data. g_free() after
- * usage.
- */
-guint8 *
-gst_byte_writer_reset_and_get_data (GstByteWriter * writer)
-{
- guint8 *data;
-
- g_return_val_if_fail (writer != NULL, NULL);
-
- data = (guint8 *) writer->parent.data;
- if (!writer->owned)
- data = g_memdup2 (data, writer->parent.size);
- writer->parent.data = NULL;
- gst_byte_writer_reset (writer);
-
- return data;
-}
-
-/**
- * gst_byte_writer_reset_and_get_buffer:
- * @writer: #GstByteWriter instance
- *
- * Resets @writer and returns the current data as buffer.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full): the current data as buffer. gst_buffer_unref()
- * after usage.
- */
-GstBuffer *
-gst_byte_writer_reset_and_get_buffer (GstByteWriter * writer)
-{
- GstBuffer *buffer;
- gpointer data;
- gsize size;
-
- g_return_val_if_fail (writer != NULL, NULL);
-
- size = writer->parent.size;
- data = gst_byte_writer_reset_and_get_data (writer);
-
- buffer = gst_buffer_new ();
- if (data != NULL) {
- gst_buffer_append_memory (buffer,
- gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
- }
-
- return buffer;
-}
-
-/**
- * gst_byte_writer_free:
- * @writer: (in) (transfer full): #GstByteWriter instance
- *
- * Frees @writer and all memory allocated by it.
- */
-void
-gst_byte_writer_free (GstByteWriter * writer)
-{
- g_return_if_fail (writer != NULL);
-
- gst_byte_writer_reset (writer);
- g_slice_free (GstByteWriter, writer);
-}
-
-/**
- * gst_byte_writer_free_and_get_data:
- * @writer: (in) (transfer full): #GstByteWriter instance
- *
- * Frees @writer and all memory allocated by it except
- * the current data, which is returned.
- *
- * Free-function: g_free
- *
- * Returns: (transfer full): the current data. g_free() after usage.
- */
-guint8 *
-gst_byte_writer_free_and_get_data (GstByteWriter * writer)
-{
- guint8 *data;
-
- g_return_val_if_fail (writer != NULL, NULL);
-
- data = gst_byte_writer_reset_and_get_data (writer);
- g_slice_free (GstByteWriter, writer);
-
- return data;
-}
-
-/**
- * gst_byte_writer_free_and_get_buffer:
- * @writer: (in) (transfer full): #GstByteWriter instance
- *
- * Frees @writer and all memory allocated by it except
- * the current data, which is returned as #GstBuffer.
- *
- * Free-function: gst_buffer_unref
- *
- * Returns: (transfer full): the current data as buffer. gst_buffer_unref()
- * after usage.
- */
-GstBuffer *
-gst_byte_writer_free_and_get_buffer (GstByteWriter * writer)
-{
- GstBuffer *buffer;
-
- g_return_val_if_fail (writer != NULL, NULL);
-
- buffer = gst_byte_writer_reset_and_get_buffer (writer);
- g_slice_free (GstByteWriter, writer);
-
- return buffer;
-}
-
-/**
- * gst_byte_writer_get_remaining:
- * @writer: #GstByteWriter instance
- *
- * Returns the remaining size of data that can still be written. If
- * -1 is returned the remaining size is only limited by system resources.
- *
- * Returns: the remaining size of data that can still be written
- */
-guint
-gst_byte_writer_get_remaining (const GstByteWriter * writer)
-{
- g_return_val_if_fail (writer != NULL, -1);
-
- if (!writer->fixed)
- return -1;
- else
- return writer->alloc_size - writer->parent.byte;
-}
-
-/**
- * gst_byte_writer_ensure_free_space:
- * @writer: #GstByteWriter instance
- * @size: Number of bytes that should be available
- *
- * Checks if enough free space from the current write cursor is
- * available and reallocates if necessary.
- *
- * Returns: %TRUE if at least @size bytes are still available
- */
-gboolean
-gst_byte_writer_ensure_free_space (GstByteWriter * writer, guint size)
-{
- return _gst_byte_writer_ensure_free_space_inline (writer, size);
-}
-
-
-#define CREATE_WRITE_FUNC(bits,type,name,write_func) \
-gboolean \
-gst_byte_writer_put_##name (GstByteWriter *writer, type val) \
-{ \
- return _gst_byte_writer_put_##name##_inline (writer, val); \
-}
-
-CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8);
-CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8);
-CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE);
-CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE);
-CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE);
-CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE);
-CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE);
-CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE);
-CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE);
-CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE);
-CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE);
-CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE);
-CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE);
-CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE);
-CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE);
-CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE);
-CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE);
-CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE);
-
-CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE);
-CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE);
-CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE);
-CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE);
-
-gboolean
-gst_byte_writer_put_data (GstByteWriter * writer, const guint8 * data,
- guint size)
-{
- return _gst_byte_writer_put_data_inline (writer, data, size);
-}
-
-gboolean
-gst_byte_writer_fill (GstByteWriter * writer, guint8 value, guint size)
-{
- return _gst_byte_writer_fill_inline (writer, value, size);
-}
-
-#define CREATE_WRITE_STRING_FUNC(bits,type) \
-gboolean \
-gst_byte_writer_put_string_utf##bits (GstByteWriter *writer, const type * data) \
-{ \
- guint size = 0; \
- \
- g_return_val_if_fail (writer != NULL, FALSE); \
- \
- /* endianness does not matter if we are looking for a NUL terminator */ \
- while (data[size] != 0) { \
- /* have prevent overflow */ \
- if (G_UNLIKELY (size == G_MAXUINT)) \
- return FALSE; \
- ++size; \
- } \
- ++size; \
- \
- if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline(writer, size * (bits / 8)))) \
- return FALSE; \
- \
- _gst_byte_writer_put_data_inline (writer, (const guint8 *) data, size * (bits / 8)); \
- \
- return TRUE; \
-}
-
-CREATE_WRITE_STRING_FUNC (8, gchar);
-CREATE_WRITE_STRING_FUNC (16, guint16);
-CREATE_WRITE_STRING_FUNC (32, guint32);
-/**
- * gst_byte_writer_put_uint8:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned 8 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint16_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 16 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint24_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 24 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint32_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 32 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint64_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned big endian 64 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint16_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 16 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint24_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 24 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint32_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 32 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_uint64_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a unsigned little endian 64 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int8:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed 8 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int16_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 16 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int24_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 24 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int32_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 32 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int64_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed big endian 64 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int16_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 16 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int24_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 24 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int32_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 32 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_int64_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a signed little endian 64 bit integer to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_float32_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a big endian 32 bit float to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_float64_be:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a big endian 64 bit float to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_float32_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a little endian 32 bit float to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_float64_le:
- * @writer: #GstByteWriter instance
- * @val: Value to write
- *
- * Writes a little endian 64 bit float to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_string_utf8:
- * @writer: #GstByteWriter instance
- * @data: (transfer none): UTF8 string to write
- *
- * Writes a NUL-terminated UTF8 string to @writer (including the terminator).
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_string_utf16:
- * @writer: #GstByteWriter instance
- * @data: (transfer none) (array zero-terminated=1): UTF16 string to write
- *
- * Writes a NUL-terminated UTF16 string to @writer (including the terminator).
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_string_utf32:
- * @writer: #GstByteWriter instance
- * @data: (transfer none) (array zero-terminated=1): UTF32 string to write
- *
- * Writes a NUL-terminated UTF32 string to @writer (including the terminator).
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_put_data:
- * @writer: #GstByteWriter instance
- * @data: (transfer none) (array length=size): Data to write
- * @size: Size of @data in bytes
- *
- * Writes @size bytes of @data to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-/**
- * gst_byte_writer_fill:
- * @writer: #GstByteWriter instance
- * @value: Value to be written
- * @size: Number of bytes to be written
- *
- * Writes @size bytes containing @value to @writer.
- *
- * Returns: %TRUE if the value could be written
- */
-
-/**
- * gst_byte_writer_put_buffer:
- * @writer: #GstByteWriter instance
- * @buffer: (transfer none): source #GstBuffer
- * @offset: offset to copy from
- * @size: total size to copy. If -1, all data is copied
- *
- * Writes @size bytes of @data to @writer.
- *
- * Returns: %TRUE if the data could be written
- *
- */
diff --git a/libs/gst/base/gstbytewriter.h b/libs/gst/base/gstbytewriter.h
deleted file mode 100644
index 365c7742d7..0000000000
--- a/libs/gst/base/gstbytewriter.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/* GStreamer byte writer
- *
- * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BYTE_WRITER_H__
-#define __GST_BYTE_WRITER_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstbytereader.h>
-
-#include <string.h>
-
-G_BEGIN_DECLS
-
-#define GST_BYTE_WRITER(writer) ((GstByteWriter *) (writer))
-
-/**
- * GstByteWriter:
- * @parent: #GstByteReader parent
- * @alloc_size: Allocation size of the data
- * @fixed: If %TRUE no reallocations are allowed
- * @owned: If %FALSE no reallocations are allowed and copies of data are returned
- *
- * A byte writer instance.
- */
-typedef struct {
- GstByteReader parent;
-
- guint alloc_size;
-
- gboolean fixed;
- gboolean owned;
-
- /* < private > */
- gpointer _gst_reserved[GST_PADDING];
-} GstByteWriter;
-
-GST_BASE_API
-GstByteWriter * gst_byte_writer_new (void) G_GNUC_MALLOC;
-
-GST_BASE_API
-GstByteWriter * gst_byte_writer_new_with_size (guint size, gboolean fixed) G_GNUC_MALLOC;
-
-GST_BASE_API
-GstByteWriter * gst_byte_writer_new_with_data (guint8 *data, guint size, gboolean initialized) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_byte_writer_init (GstByteWriter *writer);
-
-GST_BASE_API
-void gst_byte_writer_init_with_size (GstByteWriter *writer, guint size, gboolean fixed);
-
-GST_BASE_API
-void gst_byte_writer_init_with_data (GstByteWriter *writer, guint8 *data,
- guint size, gboolean initialized);
-GST_BASE_API
-void gst_byte_writer_free (GstByteWriter *writer);
-
-GST_BASE_API
-guint8 * gst_byte_writer_free_and_get_data (GstByteWriter *writer);
-
-GST_BASE_API
-GstBuffer * gst_byte_writer_free_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC;
-
-GST_BASE_API
-void gst_byte_writer_reset (GstByteWriter *writer);
-
-GST_BASE_API
-guint8 * gst_byte_writer_reset_and_get_data (GstByteWriter *writer);
-
-GST_BASE_API
-GstBuffer * gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC;
-
-/**
- * gst_byte_writer_get_pos:
- * @writer: #GstByteWriter instance
- *
- * Returns: The current position of the read/write cursor
- */
-/**
- * gst_byte_writer_set_pos:
- * @writer: #GstByteWriter instance
- * @pos: new position
- *
- * Sets the current read/write cursor of @writer. The new position
- * can only be between 0 and the current size.
- *
- * Returns: %TRUE if the new position could be set
- */
-/**
- * gst_byte_writer_get_size:
- * @writer: #GstByteWriter instance
- *
- * Returns: The current, initialized size of the data
- */
-static inline guint
-gst_byte_writer_get_pos (const GstByteWriter *writer)
-{
- return gst_byte_reader_get_pos ((const GstByteReader *) writer);
-}
-
-static inline gboolean
-gst_byte_writer_set_pos (GstByteWriter *writer, guint pos)
-{
- return gst_byte_reader_set_pos (GST_BYTE_READER (writer), pos);
-}
-
-static inline guint
-gst_byte_writer_get_size (const GstByteWriter *writer)
-{
- return gst_byte_reader_get_size ((const GstByteReader *) writer);
-}
-
-GST_BASE_API
-guint gst_byte_writer_get_remaining (const GstByteWriter *writer);
-
-GST_BASE_API
-gboolean gst_byte_writer_ensure_free_space (GstByteWriter *writer, guint size);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint8 (GstByteWriter *writer, guint8 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int8 (GstByteWriter *writer, gint8 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint16_be (GstByteWriter *writer, guint16 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint16_le (GstByteWriter *writer, guint16 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int16_be (GstByteWriter *writer, gint16 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int16_le (GstByteWriter *writer, gint16 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint24_be (GstByteWriter *writer, guint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint24_le (GstByteWriter *writer, guint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int24_be (GstByteWriter *writer, gint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int24_le (GstByteWriter *writer, gint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint32_be (GstByteWriter *writer, guint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint32_le (GstByteWriter *writer, guint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int32_be (GstByteWriter *writer, gint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int32_le (GstByteWriter *writer, gint32 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint64_be (GstByteWriter *writer, guint64 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_uint64_le (GstByteWriter *writer, guint64 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int64_be (GstByteWriter *writer, gint64 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_int64_le (GstByteWriter *writer, gint64 val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_float32_be (GstByteWriter *writer, gfloat val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_float32_le (GstByteWriter *writer, gfloat val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_float64_be (GstByteWriter *writer, gdouble val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_float64_le (GstByteWriter *writer, gdouble val);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_data (GstByteWriter *writer, const guint8 *data, guint size);
-
-GST_BASE_API
-gboolean gst_byte_writer_fill (GstByteWriter *writer, guint8 value, guint size);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_string_utf8 (GstByteWriter *writer, const gchar *data);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_string_utf16 (GstByteWriter *writer, const guint16 *data);
-
-GST_BASE_API
-gboolean gst_byte_writer_put_string_utf32 (GstByteWriter *writer, const guint32 *data);
-gboolean gst_byte_writer_put_buffer (GstByteWriter *writer, GstBuffer * buffer, gsize offset, gssize size);
-
-/**
- * gst_byte_writer_put_string:
- * @writer: #GstByteWriter instance
- * @data: (in) (array zero-terminated=1): Null terminated string
- *
- * Write a NUL-terminated string to @writer (including the terminator). The
- * string is assumed to be in an 8-bit encoding (e.g. ASCII,UTF-8 or
- * ISO-8859-1).
- *
- * Returns: %TRUE if the string could be written
- */
-#define gst_byte_writer_put_string(writer, data) \
- gst_byte_writer_put_string_utf8(writer, data)
-
-static inline guint
-_gst_byte_writer_next_pow2 (guint n)
-{
- guint ret = 16;
-
- /* We start with 16, smaller allocations make no sense */
-
- while (ret < n && ret > 0)
- ret <<= 1;
-
- return ret ? ret : n;
-}
-
-static inline gboolean
-_gst_byte_writer_ensure_free_space_inline (GstByteWriter * writer, guint size)
-{
- gpointer data;
-
- if (G_LIKELY (size <= writer->alloc_size - writer->parent.byte))
- return TRUE;
- if (G_UNLIKELY (writer->fixed || !writer->owned))
- return FALSE;
- if (G_UNLIKELY (writer->parent.byte > G_MAXUINT - size))
- return FALSE;
-
- writer->alloc_size = _gst_byte_writer_next_pow2 (writer->parent.byte + size);
- data = g_try_realloc ((guint8 *) writer->parent.data, writer->alloc_size);
- if (G_UNLIKELY (data == NULL))
- return FALSE;
-
- writer->parent.data = (guint8 *) data;
-
- return TRUE;
-}
-
-#define __GST_BYTE_WRITER_CREATE_WRITE_FUNC(bits,type,name,write_func) \
-static inline void \
-gst_byte_writer_put_##name##_unchecked (GstByteWriter *writer, type val) \
-{ \
- guint8 *write_data; \
- \
- write_data = (guint8 *) writer->parent.data + writer->parent.byte; \
- write_func (write_data, val); \
- writer->parent.byte += bits/8; \
- writer->parent.size = MAX (writer->parent.size, writer->parent.byte); \
-} \
-\
-static inline gboolean \
-_gst_byte_writer_put_##name##_inline (GstByteWriter *writer, type val) \
-{ \
- g_return_val_if_fail (writer != NULL, FALSE); \
- \
- if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline(writer, bits/8))) \
- return FALSE; \
- \
- gst_byte_writer_put_##name##_unchecked (writer, val); \
- \
- return TRUE; \
-}
-
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE)
-
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE)
-__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE)
-
-#undef __GST_BYTE_WRITER_CREATE_WRITE_FUNC
-
-static inline void
-gst_byte_writer_put_data_unchecked (GstByteWriter * writer, const guint8 * data,
- guint size)
-{
- memcpy ((guint8 *) & writer->parent.data[writer->parent.byte], data, size);
- writer->parent.byte += size;
- writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
-}
-
-static inline gboolean
-_gst_byte_writer_put_data_inline (GstByteWriter * writer, const guint8 * data,
- guint size)
-{
- g_return_val_if_fail (writer != NULL, FALSE);
-
- if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
- return FALSE;
-
- gst_byte_writer_put_data_unchecked (writer, data, size);
-
- return TRUE;
-}
-
-static inline void
-gst_byte_writer_fill_unchecked (GstByteWriter * writer, guint8 value, guint size)
-{
- memset ((guint8 *) & writer->parent.data[writer->parent.byte], value, size);
- writer->parent.byte += size;
- writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
-}
-
-static inline gboolean
-_gst_byte_writer_fill_inline (GstByteWriter * writer, guint8 value, guint size)
-{
- g_return_val_if_fail (writer != NULL, FALSE);
-
- if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
- return FALSE;
-
- gst_byte_writer_fill_unchecked (writer, value, size);
-
- return TRUE;
-}
-
-static inline void
-gst_byte_writer_put_buffer_unchecked (GstByteWriter * writer, GstBuffer * buffer,
- gsize offset, gssize size)
-{
- if (size == -1) {
- size = gst_buffer_get_size (buffer);
-
- if (offset >= (gsize) size)
- return;
-
- size -= offset;
- }
-
- gst_buffer_extract (buffer, offset,
- (guint8 *) & writer->parent.data[writer->parent.byte], size);
- writer->parent.byte += size;
- writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
-}
-
-static inline gboolean
-_gst_byte_writer_put_buffer_inline (GstByteWriter * writer, GstBuffer * buffer,
- gsize offset, gssize size)
-{
- g_return_val_if_fail (writer != NULL, FALSE);
- g_return_val_if_fail (size >= -1, FALSE);
-
- if (size == -1) {
- size = gst_buffer_get_size (buffer);
-
- if (offset >= (gsize) size)
- return TRUE;
-
- size -= offset;
- }
-
- if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
- return FALSE;
-
- gst_byte_writer_put_buffer_unchecked (writer, buffer, offset, size);
-
- return TRUE;
-}
-
-#ifndef GST_BYTE_WRITER_DISABLE_INLINES
-
-/* we use defines here so we can add the G_LIKELY() */
-
-#define gst_byte_writer_ensure_free_space(writer, size) \
- G_LIKELY (_gst_byte_writer_ensure_free_space_inline (writer, size))
-#define gst_byte_writer_put_uint8(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint8_inline (writer, val))
-#define gst_byte_writer_put_int8(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int8_inline (writer, val))
-#define gst_byte_writer_put_uint16_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint16_be_inline (writer, val))
-#define gst_byte_writer_put_uint16_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint16_le_inline (writer, val))
-#define gst_byte_writer_put_int16_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int16_be_inline (writer, val))
-#define gst_byte_writer_put_int16_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int16_le_inline (writer, val))
-#define gst_byte_writer_put_uint24_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint24_be_inline (writer, val))
-#define gst_byte_writer_put_uint24_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint24_le_inline (writer, val))
-#define gst_byte_writer_put_int24_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int24_be_inline (writer, val))
-#define gst_byte_writer_put_int24_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int24_le_inline (writer, val))
-#define gst_byte_writer_put_uint32_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint32_be_inline (writer, val))
-#define gst_byte_writer_put_uint32_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint32_le_inline (writer, val))
-#define gst_byte_writer_put_int32_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int32_be_inline (writer, val))
-#define gst_byte_writer_put_int32_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int32_le_inline (writer, val))
-#define gst_byte_writer_put_uint64_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint64_be_inline (writer, val))
-#define gst_byte_writer_put_uint64_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_uint64_le_inline (writer, val))
-#define gst_byte_writer_put_int64_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int64_be_inline (writer, val))
-#define gst_byte_writer_put_int64_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_int64_le_inline (writer, val))
-
-#define gst_byte_writer_put_float32_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_float32_be_inline (writer, val))
-#define gst_byte_writer_put_float32_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_float32_le_inline (writer, val))
-#define gst_byte_writer_put_float64_be(writer, val) \
- G_LIKELY (_gst_byte_writer_put_float64_be_inline (writer, val))
-#define gst_byte_writer_put_float64_le(writer, val) \
- G_LIKELY (_gst_byte_writer_put_float64_le_inline (writer, val))
-
-#define gst_byte_writer_put_data(writer, data, size) \
- G_LIKELY (_gst_byte_writer_put_data_inline (writer, data, size))
-#define gst_byte_writer_fill(writer, val, size) \
- G_LIKELY (_gst_byte_writer_fill_inline (writer, val, size))
-#define gst_byte_writer_put_buffer(writer, buffer, offset, size) \
- G_LIKELY (_gst_byte_writer_put_buffer_inline (writer, buffer, offset, size))
-
-#endif
-
-G_END_DECLS
-
-#endif /* __GST_BYTE_WRITER_H__ */
diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c
deleted file mode 100644
index b6f92159c0..0000000000
--- a/libs/gst/base/gstcollectpads.c
+++ /dev/null
@@ -1,2319 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sourceforge.net>
- * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstcollectpads
- * @title: GstCollectPads
- * @short_description: manages a set of pads that operate in collect mode
- *
- * 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.
- *
- * * Collectpads are created with gst_collect_pads_new(). A callback should then
- * be installed with gst_collect_pads_set_function ().
- *
- * * Pads are added to the collection with gst_collect_pads_add_pad()/
- * gst_collect_pads_remove_pad(). The pad has to be a sinkpad. When added,
- * the chain, event and query functions of the pad are overridden. The
- * element_private of the pad is used to store private information for the
- * collectpads.
- *
- * * For each pad, data is queued in the _chain function or by
- * performing a pull_range.
- *
- * * When data is queued on all pads in waiting mode, the callback function is called.
- *
- * * 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.
- *
- * * Data can also be dequeued in byte units using the gst_collect_pads_available(),
- * gst_collect_pads_read_buffer() and gst_collect_pads_flush() calls.
- *
- * * 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 collectpads.
- * 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.
- *
- * * gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode.
- * CollectPads element is not waiting for data to be collected on non-waiting pads.
- * Thus these pads may but need not have data when the callback is called.
- * All pads are in waiting mode by default.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gst/gst_private.h>
-
-#include "gstcollectpads.h"
-
-#include "../../../gst/glib-compat-private.h"
-
-GST_DEBUG_CATEGORY_STATIC (collect_pads_debug);
-#define GST_CAT_DEFAULT collect_pads_debug
-
-struct _GstCollectDataPrivate
-{
- /* refcounting for struct, and destroy callback */
- GstCollectDataDestroyNotify destroy_notify;
- gint refcount;
-};
-
-struct _GstCollectPadsPrivate
-{
- /* with LOCK and/or STREAM_LOCK */
- gboolean started;
-
- /* with STREAM_LOCK */
- guint32 cookie; /* pad_list cookie */
- guint numpads; /* number of pads in @data */
- guint queuedpads; /* number of pads with a buffer */
- guint eospads; /* number of pads that are EOS */
- GstClockTime earliest_time; /* Current earliest time */
- GstCollectData *earliest_data; /* Pad data for current earliest time */
-
- /* with LOCK */
- GSList *pad_list; /* list of GstCollectData* */
- guint32 pad_cookie; /* updated cookie */
-
- GstCollectPadsFunction func; /* function and user_data for callback */
- gpointer user_data;
- GstCollectPadsBufferFunction buffer_func; /* function and user_data for buffer callback */
- gpointer buffer_user_data;
- GstCollectPadsCompareFunction compare_func;
- gpointer compare_user_data;
- GstCollectPadsEventFunction event_func; /* function and data for event callback */
- gpointer event_user_data;
- GstCollectPadsQueryFunction query_func;
- gpointer query_user_data;
- GstCollectPadsClipFunction clip_func;
- gpointer clip_user_data;
- GstCollectPadsFlushFunction flush_func;
- gpointer flush_user_data;
-
- /* no other lock needed */
- GMutex evt_lock; /* these make up sort of poor man's event signaling */
- GCond evt_cond;
- guint32 evt_cookie;
-
- gboolean seeking;
- gboolean pending_flush_start;
- gboolean pending_flush_stop;
-};
-
-#define parent_class gst_collect_pads_parent_class
-G_DEFINE_TYPE_WITH_PRIVATE (GstCollectPads, gst_collect_pads, GST_TYPE_OBJECT);
-
-static void gst_collect_pads_clear (GstCollectPads * pads,
- GstCollectData * data);
-static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstObject * parent,
- GstBuffer * buffer);
-static gboolean gst_collect_pads_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
-static gboolean gst_collect_pads_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-static void gst_collect_pads_finalize (GObject * object);
-static GstFlowReturn gst_collect_pads_default_collected (GstCollectPads *
- pads, gpointer user_data);
-static gint gst_collect_pads_default_compare_func (GstCollectPads * pads,
- GstCollectData * data1, GstClockTime timestamp1, GstCollectData * data2,
- GstClockTime timestamp2, gpointer user_data);
-static gboolean gst_collect_pads_recalculate_full (GstCollectPads * pads);
-static void ref_data (GstCollectData * data);
-static void unref_data (GstCollectData * data);
-
-static gboolean gst_collect_pads_event_default_internal (GstCollectPads *
- pads, GstCollectData * data, GstEvent * event, gpointer user_data);
-static gboolean gst_collect_pads_query_default_internal (GstCollectPads *
- pads, GstCollectData * data, GstQuery * query, gpointer user_data);
-
-
-/* Some properties are protected by LOCK, others by STREAM_LOCK
- * However, manipulating either of these partitions may require
- * to signal/wake a _WAIT, so use a separate (sort of) event to prevent races
- * Alternative implementations are possible, e.g. some low-level re-implementing
- * of the 2 above locks to drop both of them atomically when going into _WAIT.
- */
-#define GST_COLLECT_PADS_GET_EVT_COND(pads) (&((GstCollectPads *)pads)->priv->evt_cond)
-#define GST_COLLECT_PADS_GET_EVT_LOCK(pads) (&((GstCollectPads *)pads)->priv->evt_lock)
-#define GST_COLLECT_PADS_EVT_WAIT(pads, cookie) G_STMT_START { \
- g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
- /* should work unless a lot of event'ing and thread starvation */\
- while (cookie == ((GstCollectPads *) pads)->priv->evt_cookie) \
- g_cond_wait (GST_COLLECT_PADS_GET_EVT_COND (pads), \
- GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
- cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \
- g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
-} G_STMT_END
-#define GST_COLLECT_PADS_EVT_WAIT_TIMED(pads, cookie, timeout) G_STMT_START { \
- gint64 end_time = g_get_monotonic_time () + timeout; \
- \
- g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
- /* should work unless a lot of event'ing and thread starvation */\
- while (cookie == ((GstCollectPads *) pads)->priv->evt_cookie) \
- g_cond_wait_until (GST_COLLECT_PADS_GET_EVT_COND (pads), \
- GST_COLLECT_PADS_GET_EVT_LOCK (pads), end_time); \
- cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \
- g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
-} G_STMT_END
-#define GST_COLLECT_PADS_EVT_BROADCAST(pads) G_STMT_START { \
- g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
- /* never mind wrap-around */ \
- ++(((GstCollectPads *) pads)->priv->evt_cookie); \
- g_cond_broadcast (GST_COLLECT_PADS_GET_EVT_COND (pads)); \
- g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
-} G_STMT_END
-#define GST_COLLECT_PADS_EVT_INIT(cookie) G_STMT_START { \
- g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
- cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \
- g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \
-} G_STMT_END
-
-static void
-gst_collect_pads_class_init (GstCollectPadsClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
-
- GST_DEBUG_CATEGORY_INIT (collect_pads_debug, "collectpads", 0,
- "GstCollectPads");
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collect_pads_finalize);
-}
-
-static void
-gst_collect_pads_init (GstCollectPads * pads)
-{
- pads->priv = gst_collect_pads_get_instance_private (pads);
-
- pads->data = NULL;
- pads->priv->cookie = 0;
- pads->priv->numpads = 0;
- pads->priv->queuedpads = 0;
- pads->priv->eospads = 0;
- pads->priv->started = FALSE;
-
- g_rec_mutex_init (&pads->stream_lock);
-
- pads->priv->func = gst_collect_pads_default_collected;
- pads->priv->user_data = NULL;
- pads->priv->event_func = NULL;
- pads->priv->event_user_data = NULL;
-
- /* members for default muxing */
- pads->priv->buffer_func = NULL;
- pads->priv->buffer_user_data = NULL;
- pads->priv->compare_func = gst_collect_pads_default_compare_func;
- pads->priv->compare_user_data = NULL;
- pads->priv->earliest_data = NULL;
- pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
-
- pads->priv->event_func = gst_collect_pads_event_default_internal;
- pads->priv->query_func = gst_collect_pads_query_default_internal;
-
- /* members to manage the pad list */
- pads->priv->pad_cookie = 0;
- pads->priv->pad_list = NULL;
-
- /* members for event */
- g_mutex_init (&pads->priv->evt_lock);
- g_cond_init (&pads->priv->evt_cond);
- pads->priv->evt_cookie = 0;
-
- pads->priv->seeking = FALSE;
- pads->priv->pending_flush_start = FALSE;
- pads->priv->pending_flush_stop = FALSE;
-}
-
-static void
-gst_collect_pads_finalize (GObject * object)
-{
- GstCollectPads *pads = GST_COLLECT_PADS (object);
-
- GST_DEBUG_OBJECT (object, "finalize");
-
- g_rec_mutex_clear (&pads->stream_lock);
-
- g_cond_clear (&pads->priv->evt_cond);
- g_mutex_clear (&pads->priv->evt_lock);
-
- /* Remove pads and free pads list */
- g_slist_foreach (pads->priv->pad_list, (GFunc) unref_data, NULL);
- g_slist_foreach (pads->data, (GFunc) unref_data, NULL);
- g_slist_free (pads->data);
- g_slist_free (pads->priv->pad_list);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/**
- * gst_collect_pads_new:
- *
- * Create a new instance of #GstCollectPads.
- *
- * MT safe.
- *
- * Returns: (transfer full): a new #GstCollectPads, or %NULL in case of an error.
- */
-GstCollectPads *
-gst_collect_pads_new (void)
-{
- GstCollectPads *newcoll;
-
- newcoll = g_object_new (GST_TYPE_COLLECT_PADS, NULL);
-
- /* clear floating flag */
- gst_object_ref_sink (newcoll);
-
- return newcoll;
-}
-
-/* Must be called with GstObject lock! */
-static void
-gst_collect_pads_set_buffer_function_locked (GstCollectPads * pads,
- GstCollectPadsBufferFunction func, gpointer user_data)
-{
- pads->priv->buffer_func = func;
- pads->priv->buffer_user_data = user_data;
-}
-
-/**
- * gst_collect_pads_set_buffer_function:
- * @pads: the collectpads to use
- * @func: (scope call): the function to set
- * @user_data: (closure): user data passed to the function
- *
- * Set the callback function and user data that will be called with
- * the oldest buffer when all pads have been collected, or %NULL on EOS.
- * If a buffer is passed, the callback owns a reference and must unref
- * it.
- *
- * MT safe.
- */
-void
-gst_collect_pads_set_buffer_function (GstCollectPads * pads,
- GstCollectPadsBufferFunction func, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_OBJECT_LOCK (pads);
- gst_collect_pads_set_buffer_function_locked (pads, func, user_data);
- GST_OBJECT_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_set_compare_function:
- * @pads: the pads to use
- * @func: (scope call): the function to set
- * @user_data: (closure): user data passed to the function
- *
- * Set the timestamp comparison function.
- *
- * MT safe.
- */
-/* NOTE allowing to change comparison seems not advisable;
-no known use-case, and collaboration with default algorithm is unpredictable.
-If custom comparing/operation is needed, just use a collect function of
-your own */
-void
-gst_collect_pads_set_compare_function (GstCollectPads * pads,
- GstCollectPadsCompareFunction func, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_OBJECT_LOCK (pads);
- pads->priv->compare_func = func;
- pads->priv->compare_user_data = user_data;
- GST_OBJECT_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_set_function:
- * @pads: the collectpads to use
- * @func: (scope call): the function to set
- * @user_data: user data passed to the function
- *
- * CollectPads provides a default collection algorithm that will determine
- * the oldest buffer available on all of its pads, and then delegate
- * to a configured callback.
- * However, if circumstances are more complicated and/or more control
- * is desired, this sets a callback that will be invoked instead when
- * all the pads added to the collection have buffers queued.
- * Evidently, this callback is not compatible with
- * gst_collect_pads_set_buffer_function() callback.
- * If this callback is set, the former will be unset.
- *
- * 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->priv->func = func;
- pads->priv->user_data = user_data;
- gst_collect_pads_set_buffer_function_locked (pads, NULL, NULL);
- GST_OBJECT_UNLOCK (pads);
-}
-
-static void
-ref_data (GstCollectData * data)
-{
- g_assert (data != NULL);
-
- g_atomic_int_inc (&(data->priv->refcount));
-}
-
-static void
-unref_data (GstCollectData * data)
-{
- g_assert (data != NULL);
- g_assert (data->priv->refcount > 0);
-
- if (!g_atomic_int_dec_and_test (&(data->priv->refcount)))
- return;
-
- if (data->priv->destroy_notify)
- data->priv->destroy_notify (data);
-
- gst_object_unref (data->pad);
- if (data->buffer) {
- gst_buffer_unref (data->buffer);
- }
- g_free (data->priv);
- g_free (data);
-}
-
-/**
- * gst_collect_pads_set_event_function:
- * @pads: the collectpads to use
- * @func: (scope call): the function to set
- * @user_data: user data passed to the function
- *
- * Set the event callback function and user data that will be called when
- * collectpads has received an event originating from one of the collected
- * pads. If the event being processed is a serialized one, this callback is
- * called with @pads STREAM_LOCK held, otherwise not. As this lock should be
- * held when calling a number of CollectPads functions, it should be acquired
- * if so (unusually) needed.
- *
- * MT safe.
- */
-void
-gst_collect_pads_set_event_function (GstCollectPads * pads,
- GstCollectPadsEventFunction func, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_OBJECT_LOCK (pads);
- pads->priv->event_func = func;
- pads->priv->event_user_data = user_data;
- GST_OBJECT_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_set_query_function:
- * @pads: the collectpads to use
- * @func: (scope call): the function to set
- * @user_data: user data passed to the function
- *
- * Set the query callback function and user data that will be called after
- * collectpads has received a query originating from one of the collected
- * pads. If the query being processed is a serialized one, this callback is
- * called with @pads STREAM_LOCK held, otherwise not. As this lock should be
- * held when calling a number of CollectPads functions, it should be acquired
- * if so (unusually) needed.
- *
- * MT safe.
- */
-void
-gst_collect_pads_set_query_function (GstCollectPads * pads,
- GstCollectPadsQueryFunction func, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_OBJECT_LOCK (pads);
- pads->priv->query_func = func;
- pads->priv->query_user_data = user_data;
- GST_OBJECT_UNLOCK (pads);
-}
-
-/**
-* gst_collect_pads_clip_running_time:
-* @pads: the collectpads to use
-* @cdata: collect data of corresponding pad
-* @buf: buffer being clipped
-* @outbuf: (allow-none) (out): output buffer with running time, or NULL if clipped
-* @user_data: user data (unused)
-*
-* Convenience clipping function that converts incoming buffer's timestamp
-* to running time, or clips the buffer if outside configured segment.
-*
-* Since 1.6, this clipping function also sets the DTS parameter of the
-* GstCollectData structure. This version of the running time DTS can be
-* negative. G_MININT64 is used to indicate invalid value.
-*/
-GstFlowReturn
-gst_collect_pads_clip_running_time (GstCollectPads * pads,
- GstCollectData * cdata, GstBuffer * buf, GstBuffer ** outbuf,
- gpointer user_data)
-{
- *outbuf = buf;
-
- /* invalid left alone and passed */
- if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS_OR_PTS (buf)))) {
- GstClockTime time;
- GstClockTime buf_dts, abs_dts;
- gint dts_sign;
-
- time = GST_BUFFER_PTS (buf);
-
- if (GST_CLOCK_TIME_IS_VALID (time)) {
- time =
- gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time);
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
- GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment %"
- GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
- gst_buffer_unref (buf);
- *outbuf = NULL;
- return GST_FLOW_OK;
- }
- }
-
- GST_LOG_OBJECT (cdata->pad, "buffer pts %" GST_TIME_FORMAT " -> %"
- GST_TIME_FORMAT " running time",
- GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time));
- *outbuf = gst_buffer_make_writable (buf);
- GST_BUFFER_PTS (*outbuf) = time;
-
- dts_sign = gst_segment_to_running_time_full (&cdata->segment,
- GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf), &abs_dts);
- buf_dts = GST_BUFFER_DTS (*outbuf);
- if (dts_sign > 0) {
- GST_BUFFER_DTS (*outbuf) = abs_dts;
- GST_COLLECT_PADS_DTS (cdata) = abs_dts;
- } else if (dts_sign < 0) {
- GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE;
- GST_COLLECT_PADS_DTS (cdata) = -((gint64) abs_dts);
- } else {
- GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE;
- GST_COLLECT_PADS_DTS (cdata) = GST_CLOCK_STIME_NONE;
- }
-
- GST_LOG_OBJECT (cdata->pad, "buffer dts %" GST_TIME_FORMAT " -> %"
- GST_STIME_FORMAT " running time", GST_TIME_ARGS (buf_dts),
- GST_STIME_ARGS (GST_COLLECT_PADS_DTS (cdata)));
- }
-
- return GST_FLOW_OK;
-}
-
-/**
- * gst_collect_pads_set_clip_function:
- * @pads: the collectpads to use
- * @clipfunc: (scope call): clip function to install
- * @user_data: user data to pass to @clip_func
- *
- * Install a clipping function that is called right after a buffer is received
- * on a pad managed by @pads. See #GstCollectPadsClipFunction for more info.
- */
-void
-gst_collect_pads_set_clip_function (GstCollectPads * pads,
- GstCollectPadsClipFunction clipfunc, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- pads->priv->clip_func = clipfunc;
- pads->priv->clip_user_data = user_data;
-}
-
-/**
- * gst_collect_pads_set_flush_function:
- * @pads: the collectpads to use
- * @func: (scope call): flush function to install
- * @user_data: user data to pass to @func
- *
- * Install a flush function that is called when the internal
- * state of all pads should be flushed as part of flushing seek
- * handling. See #GstCollectPadsFlushFunction for more info.
- *
- * Since: 1.4
- */
-void
-gst_collect_pads_set_flush_function (GstCollectPads * pads,
- GstCollectPadsFlushFunction func, gpointer user_data)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- pads->priv->flush_func = func;
- pads->priv->flush_user_data = user_data;
-}
-
-/**
- * gst_collect_pads_add_pad:
- * @pads: the collectpads to use
- * @pad: (transfer none): the pad to add
- * @size: the size of the returned #GstCollectData structure
- * @destroy_notify: (scope async): function to be called before the returned
- * #GstCollectData structure is freed
- * @lock: whether to lock this pad in usual waiting state
- *
- * Add a pad to the collection of collect pads. The pad has to be
- * a sinkpad. The refcount of the pad is incremented. Use
- * gst_collect_pads_remove_pad() to remove the pad from the collection
- * again.
- *
- * You specify a size for the returned #GstCollectData structure
- * so that you can use it to store additional information.
- *
- * You can also specify a #GstCollectDataDestroyNotify that will be called
- * just before the #GstCollectData structure is freed. It is passed the
- * pointer to the structure and should free any custom memory and resources
- * allocated for it.
- *
- * Keeping a pad locked in waiting state is only relevant when using
- * the default collection algorithm (providing the oldest buffer).
- * It ensures a buffer must be available on this pad for a collection
- * to take place. This is of typical use to a muxer element where
- * non-subtitle streams should always be in waiting state,
- * e.g. to assure that caps information is available on all these streams
- * when initial headers have to be written.
- *
- * The pad will be automatically activated in push mode when @pads is
- * started.
- *
- * MT safe.
- *
- * Returns: (nullable) (transfer none): a new #GstCollectData to identify the
- * new pad. Or %NULL if wrong parameters are supplied.
- */
-GstCollectData *
-gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size,
- GstCollectDataDestroyNotify destroy_notify, gboolean lock)
-{
- 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);
-
- GST_DEBUG_OBJECT (pads, "adding pad %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- data = g_malloc0 (size);
- data->priv = g_new0 (GstCollectDataPrivate, 1);
- data->collect = pads;
- data->pad = gst_object_ref (pad);
- data->buffer = NULL;
- data->pos = 0;
- gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
- data->state = GST_COLLECT_PADS_STATE_WAITING;
- data->state |= lock ? GST_COLLECT_PADS_STATE_LOCKED : 0;
- data->priv->refcount = 1;
- data->priv->destroy_notify = destroy_notify;
- data->ABI.abi.dts = G_MININT64;
-
- GST_OBJECT_LOCK (pads);
- GST_OBJECT_LOCK (pad);
- gst_pad_set_element_private (pad, data);
- GST_OBJECT_UNLOCK (pad);
- pads->priv->pad_list = g_slist_append (pads->priv->pad_list, 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_query_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_query));
- /* backward compat, also add to data if stopped, so that the element already
- * has this in the public data list before going PAUSED (typically)
- * this can only be done when we are stopped because we don't take the
- * STREAM_LOCK to protect the pads->data list. */
- if (!pads->priv->started) {
- pads->data = g_slist_append (pads->data, data);
- ref_data (data);
- }
- /* activate the pad when needed */
- if (pads->priv->started)
- gst_pad_set_active (pad, TRUE);
- pads->priv->pad_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 collectpads to use
- * @pad: (transfer none): the pad to remove
- *
- * Remove a pad from the collection of collect pads. This function will also
- * free the #GstCollectData and all the resources that were allocated with
- * gst_collect_pads_add_pad().
- *
- * The pad will be deactivated automatically when @pads is stopped.
- *
- * MT safe.
- *
- * Returns: %TRUE if the pad could be removed.
- */
-gboolean
-gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
-{
- GstCollectData *data;
- 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_DEBUG_OBJECT (pads, "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- GST_OBJECT_LOCK (pads);
- list =
- g_slist_find_custom (pads->priv->pad_list, pad, (GCompareFunc) find_pad);
- if (!list)
- goto unknown_pad;
-
- data = (GstCollectData *) list->data;
-
- GST_DEBUG_OBJECT (pads, "found pad %s:%s at %p", GST_DEBUG_PAD_NAME (pad),
- data);
-
- /* clear the stuff we configured */
- gst_pad_set_chain_function (pad, NULL);
- gst_pad_set_event_function (pad, NULL);
- GST_OBJECT_LOCK (pad);
- gst_pad_set_element_private (pad, NULL);
- GST_OBJECT_UNLOCK (pad);
-
- /* backward compat, also remove from data if stopped, note that this function
- * can only be called when we are stopped because we don't take the
- * STREAM_LOCK to protect the pads->data list. */
- if (!pads->priv->started) {
- GSList *dlist;
-
- dlist = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
- if (dlist) {
- GstCollectData *pdata = dlist->data;
-
- pads->data = g_slist_delete_link (pads->data, dlist);
- unref_data (pdata);
- }
- }
- /* remove from the pad list */
- pads->priv->pad_list = g_slist_delete_link (pads->priv->pad_list, list);
- pads->priv->pad_cookie++;
-
- /* signal waiters because something changed */
- GST_COLLECT_PADS_EVT_BROADCAST (pads);
-
- /* deactivate the pad when needed */
- if (!pads->priv->started)
- gst_pad_set_active (pad, FALSE);
-
- /* clean and free the collect data */
- unref_data (data);
-
- GST_OBJECT_UNLOCK (pads);
-
- return TRUE;
-
-unknown_pad:
- {
- GST_WARNING_OBJECT (pads, "cannot remove unknown pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- GST_OBJECT_UNLOCK (pads);
- return FALSE;
- }
-}
-
-/*
- * Must be called with STREAM_LOCK and OBJECT_LOCK.
- */
-static void
-gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads,
- gboolean flushing)
-{
- GSList *walk = NULL;
-
- GST_DEBUG ("sink-pads flushing=%d", flushing);
-
- /* Update the pads flushing flag */
- for (walk = pads->priv->pad_list; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = walk->data;
-
- if (GST_IS_PAD (cdata->pad)) {
- GST_OBJECT_LOCK (cdata->pad);
- if (flushing)
- GST_PAD_SET_FLUSHING (cdata->pad);
- else
- GST_PAD_UNSET_FLUSHING (cdata->pad);
- if (flushing)
- GST_COLLECT_PADS_STATE_SET (cdata, GST_COLLECT_PADS_STATE_FLUSHING);
- else
- GST_COLLECT_PADS_STATE_UNSET (cdata, GST_COLLECT_PADS_STATE_FLUSHING);
- gst_collect_pads_clear (pads, cdata);
- GST_OBJECT_UNLOCK (cdata->pad);
- }
- }
-
- /* inform _chain of changes */
- GST_COLLECT_PADS_EVT_BROADCAST (pads);
-}
-
-/**
- * gst_collect_pads_set_flushing:
- * @pads: the collectpads to use
- * @flushing: desired state of the pads
- *
- * Change the flushing state of all the pads in the collection. No pad
- * is able to accept anymore data when @flushing is %TRUE. Calling this
- * function with @flushing %FALSE makes @pads accept data again.
- * Caller must ensure that downstream streaming (thread) is not blocked,
- * e.g. by sending a FLUSH_START downstream.
- *
- * MT safe.
- */
-void
-gst_collect_pads_set_flushing (GstCollectPads * pads, gboolean flushing)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- /* NOTE since this eventually calls _pop, some (STREAM_)LOCK is needed here */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- GST_OBJECT_LOCK (pads);
- gst_collect_pads_set_flushing_unlocked (pads, flushing);
- GST_OBJECT_UNLOCK (pads);
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_start:
- * @pads: the collectpads to use
- *
- * Starts the processing of data in the collect_pads.
- *
- * MT safe.
- */
-void
-gst_collect_pads_start (GstCollectPads * pads)
-{
- GSList *collected;
-
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_DEBUG_OBJECT (pads, "starting collect pads");
-
- /* make sure stop and collect cannot be called anymore */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
-
- /* make pads streamable */
- GST_OBJECT_LOCK (pads);
-
- /* loop over the master pad list and reset the segment */
- collected = pads->priv->pad_list;
- for (; collected; collected = g_slist_next (collected)) {
- GstCollectData *data;
-
- data = collected->data;
- gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
- }
-
- gst_collect_pads_set_flushing_unlocked (pads, FALSE);
-
- /* Start collect pads */
- pads->priv->started = TRUE;
- GST_OBJECT_UNLOCK (pads);
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_stop:
- * @pads: the collectpads 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)
-{
- GSList *collected;
-
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
-
- GST_DEBUG_OBJECT (pads, "stopping collect pads");
-
- /* make sure collect and start cannot be called anymore */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
-
- /* make pads not accept data anymore */
- GST_OBJECT_LOCK (pads);
- gst_collect_pads_set_flushing_unlocked (pads, TRUE);
-
- /* Stop collect pads */
- pads->priv->started = FALSE;
- pads->priv->eospads = 0;
- pads->priv->queuedpads = 0;
-
- /* loop over the master pad list and flush buffers */
- collected = pads->priv->pad_list;
- for (; collected; collected = g_slist_next (collected)) {
- GstCollectData *data;
- GstBuffer **buffer_p;
-
- data = collected->data;
- if (data->buffer) {
- buffer_p = &data->buffer;
- gst_buffer_replace (buffer_p, NULL);
- data->pos = 0;
- }
- GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS);
- }
-
- if (pads->priv->earliest_data)
- unref_data (pads->priv->earliest_data);
- pads->priv->earliest_data = NULL;
- pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
-
- GST_OBJECT_UNLOCK (pads);
- /* Wake them up so they can end the chain functions. */
- GST_COLLECT_PADS_EVT_BROADCAST (pads);
-
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-}
-
-/**
- * gst_collect_pads_peek:
- * @pads: the collectpads to peek
- * @data: the data to use
- *
- * Peek at the buffer currently queued in @data. This function
- * should be called with the @pads STREAM_LOCK held, such as in the callback
- * handler.
- *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no
- * buffer is queued. should unref the buffer after usage.
- */
-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);
-
- if ((result = data->buffer))
- gst_buffer_ref (result);
-
- GST_DEBUG_OBJECT (pads, "Peeking at pad %s:%s: buffer=%" GST_PTR_FORMAT,
- GST_DEBUG_PAD_NAME (data->pad), result);
-
- return result;
-}
-
-/**
- * gst_collect_pads_pop:
- * @pads: the collectpads to pop
- * @data: the data to use
- *
- * Pop the buffer currently queued in @data. This function
- * should be called with the @pads STREAM_LOCK held, such as in the callback
- * handler.
- *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no
- * buffer was queued. You should unref the buffer after usage.
- */
-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);
-
- if ((result = data->buffer)) {
- data->buffer = NULL;
- data->pos = 0;
- /* one less pad with queued data now */
- if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING))
- pads->priv->queuedpads--;
- }
-
- GST_COLLECT_PADS_EVT_BROADCAST (pads);
-
- GST_DEBUG_OBJECT (pads, "Pop buffer on pad %s:%s: buffer=%" GST_PTR_FORMAT,
- GST_DEBUG_PAD_NAME (data->pad), result);
-
- return result;
-}
-
-/* pop and unref the currently queued buffer, should be called with STREAM_LOCK
- * held */
-static void
-gst_collect_pads_clear (GstCollectPads * pads, GstCollectData * data)
-{
- GstBuffer *buf;
-
- if ((buf = gst_collect_pads_pop (pads, data)))
- gst_buffer_unref (buf);
-}
-
-/**
- * gst_collect_pads_available:
- * @pads: the collectpads 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 STREAM_LOCK held, such as
- * in the callback.
- *
- * MT safe.
- *
- * Returns: The maximum number of bytes queued on all pads. This function
- * returns 0 if a pad has no queued buffer.
- */
-/* we might pre-calculate this in some struct field,
- * but would then have to maintain this in _chain and particularly _pop, etc,
- * even if element is never interested in this information */
-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);
-
- collected = pads->data;
- for (; collected; collected = g_slist_next (collected)) {
- GstCollectData *pdata;
- GstBuffer *buffer;
- gint size;
-
- pdata = (GstCollectData *) collected->data;
-
- /* ignore pad with EOS */
- if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (pdata,
- GST_COLLECT_PADS_STATE_EOS))) {
- GST_DEBUG_OBJECT (pads, "pad %p is EOS", pdata);
- continue;
- }
-
- /* an empty buffer without EOS is weird when we get here.. */
- if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) {
- GST_WARNING_OBJECT (pads, "pad %p has no buffer", pdata);
- goto not_filled;
- }
-
- /* this is the size left of the buffer */
- size = gst_buffer_get_size (buffer) - pdata->pos;
- GST_DEBUG_OBJECT (pads, "pad %p has %d bytes left", pdata, size);
-
- /* need to return the min of all available data */
- if (size < result)
- result = size;
- }
- /* nothing changed, all must be EOS then, return 0 */
- if (G_UNLIKELY (result == G_MAXUINT))
- result = 0;
-
- return result;
-
-not_filled:
- {
- return 0;
- }
-}
-
-/**
- * gst_collect_pads_flush:
- * @pads: the collectpads 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 STREAM_LOCK held, such as
- * in the callback.
- *
- * MT safe.
- *
- * Returns: The number of bytes flushed This can be less than @size and
- * is 0 if the pad was end-of-stream.
- */
-guint
-gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,
- guint size)
-{
- guint flushsize;
- gsize bsize;
- GstBuffer *buffer;
-
- 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);
-
- /* no buffer, must be EOS */
- if ((buffer = data->buffer) == NULL)
- return 0;
-
- bsize = gst_buffer_get_size (buffer);
-
- /* this is what we can flush at max */
- flushsize = MIN (size, bsize - data->pos);
-
- data->pos += size;
-
- if (data->pos >= bsize)
- /* _clear will also reset data->pos to 0 */
- gst_collect_pads_clear (pads, data);
-
- return flushsize;
-}
-
-/**
- * gst_collect_pads_read_buffer:
- * @pads: the collectpads to query
- * @data: the data to use
- * @size: the number of bytes to read
- *
- * Get a subbuffer of @size bytes from the given pad @data.
- *
- * This function should be called with @pads STREAM_LOCK held, such as in the
- * callback.
- *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can
- * be less that requested. A return of %NULL signals that the pad is
- * end-of-stream. Unref the buffer after use.
- */
-GstBuffer *
-gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
- guint size)
-{
- guint readsize, buf_size;
- GstBuffer *buffer;
-
- 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);
-
- /* no buffer, must be EOS */
- if ((buffer = data->buffer) == NULL)
- return NULL;
-
- buf_size = gst_buffer_get_size (buffer);
- readsize = MIN (size, buf_size - data->pos);
-
- return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos,
- readsize);
-}
-
-/**
- * gst_collect_pads_take_buffer:
- * @pads: the collectpads to query
- * @data: the data to use
- * @size: the number of bytes to read
- *
- * Get a subbuffer of @size bytes from the given pad @data. Flushes the amount
- * of read bytes.
- *
- * This function should be called with @pads STREAM_LOCK held, such as in the
- * callback.
- *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can
- * be less that requested. A return of %NULL signals that the pad is
- * end-of-stream. Unref the buffer after use.
- */
-GstBuffer *
-gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data,
- guint size)
-{
- GstBuffer *buffer = gst_collect_pads_read_buffer (pads, data, size);
-
- if (buffer) {
- gst_collect_pads_flush (pads, data, gst_buffer_get_size (buffer));
- }
- return buffer;
-}
-
-/**
- * gst_collect_pads_set_waiting:
- * @pads: the collectpads
- * @data: the data to use
- * @waiting: boolean indicating whether this pad should operate
- * in waiting or non-waiting mode
- *
- * Sets a pad to waiting or non-waiting mode, if at least this pad
- * has not been created with locked waiting state,
- * in which case nothing happens.
- *
- * This function should be called with @pads STREAM_LOCK held, such as
- * in the callback.
- *
- * MT safe.
- */
-void
-gst_collect_pads_set_waiting (GstCollectPads * pads, GstCollectData * data,
- gboolean waiting)
-{
- g_return_if_fail (pads != NULL);
- g_return_if_fail (GST_IS_COLLECT_PADS (pads));
- g_return_if_fail (data != NULL);
-
- GST_DEBUG_OBJECT (pads, "Setting pad %s to waiting %d, locked %d",
- GST_PAD_NAME (data->pad), waiting,
- GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_LOCKED));
-
- /* Do something only on a change and if not locked */
- if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_LOCKED) &&
- (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING) !=
- ! !waiting)) {
- /* Set waiting state for this pad */
- if (waiting)
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_WAITING);
- else
- GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_WAITING);
- /* Update number of queued pads if needed */
- if (!data->buffer &&
- !GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS)) {
- if (waiting)
- pads->priv->queuedpads--;
- else
- pads->priv->queuedpads++;
- }
-
- /* signal waiters because something changed */
- GST_COLLECT_PADS_EVT_BROADCAST (pads);
- }
-}
-
-/* see if pads were added or removed and update our stats. Any pad
- * added after releasing the LOCK will get collected in the next
- * round.
- *
- * We can do a quick check by checking the cookies, that get changed
- * whenever the pad list is updated.
- *
- * Must be called with STREAM_LOCK.
- */
-static void
-gst_collect_pads_check_pads (GstCollectPads * pads)
-{
- /* the master list and cookie are protected with LOCK */
- GST_OBJECT_LOCK (pads);
- if (G_UNLIKELY (pads->priv->pad_cookie != pads->priv->cookie)) {
- GSList *collected;
-
- /* clear list and stats */
- g_slist_foreach (pads->data, (GFunc) unref_data, NULL);
- g_slist_free (pads->data);
- pads->data = NULL;
- pads->priv->numpads = 0;
- pads->priv->queuedpads = 0;
- pads->priv->eospads = 0;
- if (pads->priv->earliest_data)
- unref_data (pads->priv->earliest_data);
- pads->priv->earliest_data = NULL;
- pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
-
- /* loop over the master pad list */
- collected = pads->priv->pad_list;
- for (; collected; collected = g_slist_next (collected)) {
- GstCollectData *data;
-
- /* update the stats */
- pads->priv->numpads++;
- data = collected->data;
- if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS))
- pads->priv->eospads++;
- else if (data->buffer || !GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_WAITING))
- pads->priv->queuedpads++;
-
- /* add to the list of pads to collect */
- ref_data (data);
- /* preserve order of adding/requesting pads */
- pads->data = g_slist_append (pads->data, data);
- }
- /* and update the cookie */
- pads->priv->cookie = pads->priv->pad_cookie;
- }
- GST_OBJECT_UNLOCK (pads);
-}
-
-/* checks if all the pads are collected and call the collectfunction
- *
- * Should be called with STREAM_LOCK.
- *
- * Returns: The #GstFlowReturn of collection.
- */
-static GstFlowReturn
-gst_collect_pads_check_collected (GstCollectPads * pads)
-{
- GstFlowReturn flow_ret = GST_FLOW_OK;
- GstCollectPadsFunction func;
- gpointer user_data;
-
- g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR);
-
- GST_OBJECT_LOCK (pads);
- func = pads->priv->func;
- user_data = pads->priv->user_data;
- GST_OBJECT_UNLOCK (pads);
-
- g_return_val_if_fail (pads->priv->func != NULL, GST_FLOW_NOT_SUPPORTED);
-
- /* check for new pads, update stats etc.. */
- gst_collect_pads_check_pads (pads);
-
- if (G_UNLIKELY (pads->priv->eospads == pads->priv->numpads)) {
- /* If all our pads are EOS just collect once to let the element
- * do its final EOS handling. */
- GST_DEBUG_OBJECT (pads, "All active pads (%d) are EOS, calling %s",
- pads->priv->numpads, GST_DEBUG_FUNCPTR_NAME (func));
-
- if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking,
- TRUE, FALSE))) {
- GST_INFO_OBJECT (pads, "finished seeking");
- }
- do {
- flow_ret = func (pads, user_data);
- } while (flow_ret == GST_FLOW_OK);
- } else {
- gboolean collected = FALSE;
-
- /* We call the collected function as long as our condition matches. */
- while (((pads->priv->queuedpads + pads->priv->eospads) >=
- pads->priv->numpads)) {
- GST_DEBUG_OBJECT (pads,
- "All active pads (%d + %d >= %d) have data, " "calling %s",
- pads->priv->queuedpads, pads->priv->eospads, pads->priv->numpads,
- GST_DEBUG_FUNCPTR_NAME (func));
-
- if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking,
- TRUE, FALSE))) {
- GST_INFO_OBJECT (pads, "finished seeking");
- }
- flow_ret = func (pads, user_data);
- collected = TRUE;
-
- /* break on error */
- if (flow_ret != GST_FLOW_OK)
- break;
- /* Don't keep looping after telling the element EOS or flushing */
- if (pads->priv->queuedpads == 0)
- break;
- }
- if (!collected)
- GST_DEBUG_OBJECT (pads, "Not all active pads (%d) have data, continuing",
- pads->priv->numpads);
- }
- return flow_ret;
-}
-
-
-/* General overview:
- * - only pad with a buffer can determine earliest_data (and earliest_time)
- * - only segment info determines (non-)waiting state
- * - ? perhaps use _stream_time for comparison
- * (which muxers might have use as well ?)
- */
-
-/*
- * Function to recalculate the waiting state of all pads.
- *
- * Must be called with STREAM_LOCK.
- *
- * Returns %TRUE if a pad was set to waiting
- * (from non-waiting state).
- */
-static gboolean
-gst_collect_pads_recalculate_waiting (GstCollectPads * pads)
-{
- GSList *collected;
- gboolean result = FALSE;
-
- /* If earliest time is not known, there is nothing to do. */
- if (pads->priv->earliest_data == NULL)
- return FALSE;
-
- for (collected = pads->data; collected; collected = g_slist_next (collected)) {
- GstCollectData *data = (GstCollectData *) collected->data;
- int cmp_res;
- GstClockTime comp_time;
-
- /* check if pad has a segment */
- if (data->segment.format == GST_FORMAT_UNDEFINED) {
- GST_WARNING_OBJECT (pads,
- "GstCollectPads has no time segment, assuming 0 based.");
- gst_segment_init (&data->segment, GST_FORMAT_TIME);
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT);
- }
-
- /* check segment format */
- if (data->segment.format != GST_FORMAT_TIME) {
- GST_ERROR_OBJECT (pads, "GstCollectPads can handle only time segments.");
- continue;
- }
-
- /* check if the waiting state should be changed */
- comp_time = data->segment.position;
- cmp_res = pads->priv->compare_func (pads, data, comp_time,
- pads->priv->earliest_data, pads->priv->earliest_time,
- pads->priv->compare_user_data);
- if (cmp_res > 0)
- /* stop waiting */
- gst_collect_pads_set_waiting (pads, data, FALSE);
- else {
- if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) {
- /* start waiting */
- gst_collect_pads_set_waiting (pads, data, TRUE);
- result = TRUE;
- }
- }
- }
-
- return result;
-}
-
-/**
- * gst_collect_pads_find_best_pad:
- * @pads: the collectpads to use
- * @data: returns the collectdata for earliest data
- * @time: returns the earliest available buffertime
- *
- * Find the oldest/best pad, i.e. pad holding the oldest buffer and
- * and return the corresponding #GstCollectData and buffertime.
- *
- * This function should be called with STREAM_LOCK held,
- * such as in the callback.
- */
-static void
-gst_collect_pads_find_best_pad (GstCollectPads * pads,
- GstCollectData ** data, GstClockTime * time)
-{
- GSList *collected;
- GstCollectData *best = NULL;
- GstClockTime best_time = GST_CLOCK_TIME_NONE;
-
- g_return_if_fail (data != NULL);
- g_return_if_fail (time != NULL);
-
- for (collected = pads->data; collected; collected = g_slist_next (collected)) {
- GstBuffer *buffer;
- GstCollectData *data = (GstCollectData *) collected->data;
- GstClockTime timestamp;
-
- buffer = gst_collect_pads_peek (pads, data);
- /* if we have a buffer check if it is better then the current best one */
- if (buffer != NULL) {
- timestamp = GST_BUFFER_DTS_OR_PTS (buffer);
- gst_buffer_unref (buffer);
- if (best == NULL || pads->priv->compare_func (pads, data, timestamp,
- best, best_time, pads->priv->compare_user_data) < 0) {
- best = data;
- best_time = timestamp;
- }
- }
- }
-
- /* set earliest time */
- *data = best;
- *time = best_time;
-
- GST_DEBUG_OBJECT (pads, "best pad %s, best time %" GST_TIME_FORMAT,
- best ? GST_PAD_NAME (((GstCollectData *) best)->pad) : "(nil)",
- GST_TIME_ARGS (best_time));
-}
-
-/*
- * Function to recalculate earliest_data and earliest_timestamp. This also calls
- * gst_collect_pads_recalculate_waiting
- *
- * Must be called with STREAM_LOCK.
- */
-static gboolean
-gst_collect_pads_recalculate_full (GstCollectPads * pads)
-{
- if (pads->priv->earliest_data)
- unref_data (pads->priv->earliest_data);
- gst_collect_pads_find_best_pad (pads, &pads->priv->earliest_data,
- &pads->priv->earliest_time);
- if (pads->priv->earliest_data)
- ref_data (pads->priv->earliest_data);
- return gst_collect_pads_recalculate_waiting (pads);
-}
-
-/*
- * Default collect callback triggered when #GstCollectPads gathered all data.
- *
- * Called with STREAM_LOCK.
- */
-static GstFlowReturn
-gst_collect_pads_default_collected (GstCollectPads * pads, gpointer user_data)
-{
- GstCollectData *best = NULL;
- GstBuffer *buffer;
- GstFlowReturn ret = GST_FLOW_OK;
- GstCollectPadsBufferFunction func;
- gpointer buffer_user_data;
-
- g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR);
-
- GST_OBJECT_LOCK (pads);
- func = pads->priv->buffer_func;
- buffer_user_data = pads->priv->buffer_user_data;
- GST_OBJECT_UNLOCK (pads);
-
- g_return_val_if_fail (func != NULL, GST_FLOW_NOT_SUPPORTED);
-
- /* Find the oldest pad at all cost */
- if (gst_collect_pads_recalculate_full (pads)) {
- /* waiting was switched on,
- * so give another thread a chance to deliver a possibly
- * older buffer; don't charge on yet with the current oldest */
- ret = GST_FLOW_OK;
- goto done;
- }
-
- best = pads->priv->earliest_data;
-
- /* No data collected means EOS. */
- if (G_UNLIKELY (best == NULL)) {
- ret = func (pads, best, NULL, buffer_user_data);
- if (ret == GST_FLOW_OK)
- ret = GST_FLOW_EOS;
- goto done;
- }
-
- /* make sure that the pad we take a buffer from is waiting;
- * otherwise popping a buffer will seem not to have happened
- * and collectpads can get into a busy loop */
- gst_collect_pads_set_waiting (pads, best, TRUE);
-
- /* Send buffer */
- buffer = gst_collect_pads_pop (pads, best);
- ret = func (pads, best, buffer, buffer_user_data);
-
- /* maybe non-waiting was forced to waiting above due to
- * newsegment events coming too sparsely,
- * so re-check to restore state to avoid hanging/waiting */
- gst_collect_pads_recalculate_full (pads);
-
-done:
- return ret;
-}
-
-/*
- * Default timestamp compare function.
- */
-static gint
-gst_collect_pads_default_compare_func (GstCollectPads * pads,
- GstCollectData * data1, GstClockTime timestamp1,
- GstCollectData * data2, GstClockTime timestamp2, gpointer user_data)
-{
-
- GST_LOG_OBJECT (pads, "comparing %" GST_TIME_FORMAT
- " and %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp1),
- GST_TIME_ARGS (timestamp2));
- /* non-valid timestamps go first as they are probably headers or so */
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp1)))
- return GST_CLOCK_TIME_IS_VALID (timestamp2) ? -1 : 0;
-
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp2)))
- return 1;
-
- /* compare timestamp */
- if (timestamp1 < timestamp2)
- return -1;
-
- if (timestamp1 > timestamp2)
- return 1;
-
- return 0;
-}
-
-/* called with STREAM_LOCK */
-static void
-gst_collect_pads_handle_position_update (GstCollectPads * pads,
- GstCollectData * data, GstClockTime new_pos)
-{
- gint cmp_res;
-
- /* If oldest time is not known, or current pad got newsegment;
- * recalculate the state */
- if (!pads->priv->earliest_data || pads->priv->earliest_data == data) {
- gst_collect_pads_recalculate_full (pads);
- goto exit;
- }
-
- /* Check if the waiting state of the pad should change. */
- cmp_res =
- pads->priv->compare_func (pads, data, new_pos,
- pads->priv->earliest_data, pads->priv->earliest_time,
- pads->priv->compare_user_data);
-
- if (cmp_res > 0)
- /* Stop waiting */
- gst_collect_pads_set_waiting (pads, data, FALSE);
-
-exit:
- return;
-
-}
-
-static GstClockTime
-gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data,
- GstClockTime time)
-{
- GstClockTime otime = time;
- GstBuffer *in, *out = NULL;
-
- if (pads->priv->clip_func) {
- in = gst_buffer_new ();
- GST_BUFFER_PTS (in) = time;
- GST_BUFFER_DTS (in) = GST_CLOCK_TIME_NONE;
- pads->priv->clip_func (pads, data, in, &out, pads->priv->clip_user_data);
- if (out) {
- otime = GST_BUFFER_PTS (out);
- gst_buffer_unref (out);
- } else {
- /* FIXME should distinguish between ahead or after segment,
- * let's assume after segment and use some large time ... */
- otime = G_MAXINT64 / 2;
- }
- }
-
- return otime;
-}
-
-/**
- * gst_collect_pads_event_default:
- * @pads: the collectpads to use
- * @data: collect data of corresponding pad
- * @event: event being processed
- * @discard: process but do not send event downstream
- *
- * Default #GstCollectPads event handling that elements should always
- * chain up to to ensure proper operation. Element might however indicate
- * event should not be forwarded downstream.
- */
-gboolean
-gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data,
- GstEvent * event, gboolean discard)
-{
- gboolean res = TRUE;
- GstCollectPadsBufferFunction buffer_func;
- GstObject *parent;
- GstPad *pad;
-
- GST_OBJECT_LOCK (pads);
- buffer_func = pads->priv->buffer_func;
- GST_OBJECT_UNLOCK (pads);
-
- pad = data->pad;
- parent = GST_OBJECT_PARENT (pad);
-
- GST_DEBUG_OBJECT (pad, "Got '%s' event", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- {
- if (g_atomic_int_get (&pads->priv->seeking)) {
- /* drop all but the first FLUSH_STARTs when seeking */
- if (!g_atomic_int_compare_and_exchange (&pads->
- priv->pending_flush_start, TRUE, FALSE))
- goto eat;
-
- /* unblock collect pads */
- gst_pad_event_default (pad, parent, event);
- event = NULL;
-
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- /* Start flushing. We never call gst_collect_pads_set_flushing (FALSE), we
- * instead wait until each pad gets its FLUSH_STOP and let that reset the pad to
- * non-flushing (which happens in gst_collect_pads_event_default).
- */
- gst_collect_pads_set_flushing (pads, TRUE);
-
- if (pads->priv->flush_func)
- pads->priv->flush_func (pads, pads->priv->flush_user_data);
-
- g_atomic_int_set (&pads->priv->pending_flush_stop, TRUE);
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- goto eat;
- } else {
- /* forward event to unblock check_collected */
- GST_DEBUG_OBJECT (pad, "forwarding flush start");
- if (!(res = gst_pad_event_default (pad, parent, event))) {
- GST_WARNING_OBJECT (pad, "forwarding flush start failed");
- }
- event = NULL;
-
- /* now unblock the chain function.
- * no cond per pad, so they all unblock,
- * non-flushing block again */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_FLUSHING);
- gst_collect_pads_clear (pads, data);
-
- /* cater for possible default muxing functionality */
- if (buffer_func) {
- /* restore to initial state */
- gst_collect_pads_set_waiting (pads, data, TRUE);
- /* if the current pad is affected, reset state, recalculate later */
- if (pads->priv->earliest_data == data) {
- unref_data (data);
- pads->priv->earliest_data = NULL;
- pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
- }
- }
-
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- goto eat;
- }
- }
- case GST_EVENT_FLUSH_STOP:
- {
- /* flush the 1 buffer queue */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_FLUSHING);
- gst_collect_pads_clear (pads, data);
- /* we need new segment info after the flush */
- gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
- GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT);
- /* if the pad was EOS, remove the EOS flag and
- * decrement the number of eospads */
- if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_EOS))) {
- if (!GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_WAITING))
- pads->priv->queuedpads++;
- if (!g_atomic_int_get (&pads->priv->seeking)) {
- pads->priv->eospads--;
- }
- GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS);
- }
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- if (g_atomic_int_get (&pads->priv->seeking)) {
- if (g_atomic_int_compare_and_exchange (&pads->priv->pending_flush_stop,
- TRUE, FALSE))
- goto forward;
- else
- goto eat;
- } else {
- goto forward;
- }
- }
- case GST_EVENT_EOS:
- {
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- /* if the pad was not EOS, make it EOS and so we
- * have one more eospad */
- if (G_LIKELY (!GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_EOS))) {
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_EOS);
- if (!GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_WAITING))
- pads->priv->queuedpads--;
- pads->priv->eospads++;
- }
- /* check if we need collecting anything, we ignore the result. */
- gst_collect_pads_check_collected (pads);
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- goto eat;
- }
- case GST_EVENT_SEGMENT:
- {
- GstSegment seg;
-
- GST_COLLECT_PADS_STREAM_LOCK (pads);
-
- gst_event_copy_segment (event, &seg);
-
- GST_DEBUG_OBJECT (data->pad, "got segment %" GST_SEGMENT_FORMAT, &seg);
-
- /* default collection can not handle other segment formats than time */
- if (buffer_func && seg.format != GST_FORMAT_TIME) {
- GST_WARNING_OBJECT (pads, "GstCollectPads default collecting "
- "can only handle time segments. Non time segment ignored.");
- goto newsegment_done;
- }
-
- /* need to update segment first */
- data->segment = seg;
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT);
-
- /* now we can use for e.g. running time */
- seg.position =
- gst_collect_pads_clip_time (pads, data, seg.start + seg.offset);
- /* update again */
- data->segment = seg;
-
- /* default muxing functionality */
- if (!buffer_func)
- goto newsegment_done;
-
- gst_collect_pads_handle_position_update (pads, data, seg.position);
-
- newsegment_done:
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- /* we must not forward this event since multiple segments will be
- * accumulated and this is certainly not what we want. */
- goto eat;
- }
- case GST_EVENT_GAP:
- {
- GstClockTime start, duration;
-
- GST_COLLECT_PADS_STREAM_LOCK (pads);
-
- gst_event_parse_gap (event, &start, &duration);
- /* FIXME, handle reverse playback case */
- if (GST_CLOCK_TIME_IS_VALID (duration))
- start += duration;
- /* we do not expect another buffer until after gap,
- * so that is our position now */
- data->segment.position = gst_collect_pads_clip_time (pads, data, start);
-
- gst_collect_pads_handle_position_update (pads, data,
- data->segment.position);
-
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- goto eat;
- }
- case GST_EVENT_STREAM_START:
- /* drop stream start events, element must create its own start event,
- * we can't just forward the first random stream start event we get */
- goto eat;
- case GST_EVENT_CAPS:
- goto eat;
- default:
- /* forward other events */
- goto forward;
- }
-
-eat:
- GST_DEBUG_OBJECT (pads, "dropping event: %" GST_PTR_FORMAT, event);
- if (event)
- gst_event_unref (event);
- return res;
-
-forward:
- if (discard)
- goto eat;
- else {
- GST_DEBUG_OBJECT (pads, "forward event: %" GST_PTR_FORMAT, event);
- return gst_pad_event_default (pad, parent, event);
- }
-}
-
-typedef struct
-{
- GstEvent *event;
- gboolean result;
-} EventData;
-
-static gboolean
-event_forward_func (GstPad * pad, EventData * data)
-{
- gboolean ret = TRUE;
- GstPad *peer = gst_pad_get_peer (pad);
-
- if (peer) {
- ret = gst_pad_send_event (peer, gst_event_ref (data->event));
- gst_object_unref (peer);
- }
-
- data->result &= ret;
- /* Always send to all pads */
- return FALSE;
-}
-
-static gboolean
-forward_event_to_all_sinkpads (GstPad * srcpad, GstEvent * event)
-{
- EventData data;
-
- data.event = event;
- data.result = TRUE;
-
- gst_pad_forward (srcpad, (GstPadForwardFunction) event_forward_func, &data);
-
- gst_event_unref (event);
-
- return data.result;
-}
-
-/**
- * gst_collect_pads_src_event_default:
- * @pads: the #GstCollectPads to use
- * @pad: src #GstPad that received the event
- * @event: event being processed
- *
- * Default #GstCollectPads event handling for the src pad of elements.
- * Elements can chain up to this to let flushing seek event handling
- * be done by #GstCollectPads.
- *
- * Since: 1.4
- */
-gboolean
-gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad,
- GstEvent * event)
-{
- GstObject *parent;
- gboolean res = TRUE;
-
- parent = GST_OBJECT_PARENT (pad);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:{
- GstSeekFlags flags;
-
- pads->priv->eospads = 0;
-
- GST_INFO_OBJECT (pads, "starting seek");
-
- gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
- if (flags & GST_SEEK_FLAG_FLUSH) {
- g_atomic_int_set (&pads->priv->seeking, TRUE);
- g_atomic_int_set (&pads->priv->pending_flush_start, TRUE);
- /* forward the seek upstream */
- res = forward_event_to_all_sinkpads (pad, event);
- event = NULL;
- if (!res) {
- g_atomic_int_set (&pads->priv->seeking, FALSE);
- g_atomic_int_set (&pads->priv->pending_flush_start, FALSE);
- }
- }
-
- GST_INFO_OBJECT (pads, "seek done, result: %d", res);
-
- break;
- }
- default:
- break;
- }
-
- if (event)
- res = gst_pad_event_default (pad, parent, event);
-
- return res;
-}
-
-static gboolean
-gst_collect_pads_event_default_internal (GstCollectPads * pads,
- GstCollectData * data, GstEvent * event, gpointer user_data)
-{
- return gst_collect_pads_event_default (pads, data, event, FALSE);
-}
-
-static gboolean
-gst_collect_pads_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- gboolean res = FALSE, need_unlock = FALSE;
- GstCollectData *data;
- GstCollectPads *pads;
- GstCollectPadsEventFunction event_func;
- gpointer event_user_data;
-
- /* some magic to get the managing collect_pads */
- GST_OBJECT_LOCK (pad);
- data = (GstCollectData *) gst_pad_get_element_private (pad);
- if (G_UNLIKELY (data == NULL))
- goto pad_removed;
- ref_data (data);
- GST_OBJECT_UNLOCK (pad);
-
- res = FALSE;
-
- pads = data->collect;
-
- GST_DEBUG_OBJECT (data->pad, "Got %s event on sink pad",
- GST_EVENT_TYPE_NAME (event));
-
- GST_OBJECT_LOCK (pads);
- event_func = pads->priv->event_func;
- event_user_data = pads->priv->event_user_data;
- GST_OBJECT_UNLOCK (pads);
-
- if (GST_EVENT_IS_SERIALIZED (event)) {
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- need_unlock = TRUE;
- }
-
- if (G_LIKELY (event_func)) {
- res = event_func (pads, data, event, event_user_data);
- }
-
- if (need_unlock)
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- unref_data (data);
- return res;
-
- /* ERRORS */
-pad_removed:
- {
- GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- return FALSE;
- }
-}
-
-/**
- * gst_collect_pads_query_default:
- * @pads: the collectpads to use
- * @data: collect data of corresponding pad
- * @query: query being processed
- * @discard: process but do not send event downstream
- *
- * Default #GstCollectPads query handling that elements should always
- * chain up to to ensure proper operation. Element might however indicate
- * query should not be forwarded downstream.
- */
-gboolean
-gst_collect_pads_query_default (GstCollectPads * pads, GstCollectData * data,
- GstQuery * query, gboolean discard)
-{
- gboolean res = TRUE;
- GstObject *parent;
- GstPad *pad;
-
- pad = data->pad;
- parent = GST_OBJECT_PARENT (pad);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_SEEKING:
- {
- GstFormat format;
-
- /* don't pass it along as some (file)sink might claim it does
- * whereas with a collectpads in between that will not likely work */
- gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
- gst_query_set_seeking (query, format, FALSE, 0, -1);
- res = TRUE;
- discard = TRUE;
- break;
- }
- default:
- break;
- }
-
- if (!discard)
- return gst_pad_query_default (pad, parent, query);
- else
- return res;
-}
-
-static gboolean
-gst_collect_pads_query_default_internal (GstCollectPads * pads,
- GstCollectData * data, GstQuery * query, gpointer user_data)
-{
- return gst_collect_pads_query_default (pads, data, query, FALSE);
-}
-
-static gboolean
-gst_collect_pads_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- gboolean res = FALSE, need_unlock = FALSE;
- GstCollectData *data;
- GstCollectPads *pads;
- GstCollectPadsQueryFunction query_func;
- gpointer query_user_data;
-
- GST_DEBUG_OBJECT (pad, "Got %s query on sink pad",
- GST_QUERY_TYPE_NAME (query));
-
- /* some magic to get the managing collect_pads */
- GST_OBJECT_LOCK (pad);
- data = (GstCollectData *) gst_pad_get_element_private (pad);
- if (G_UNLIKELY (data == NULL))
- goto pad_removed;
- ref_data (data);
- GST_OBJECT_UNLOCK (pad);
-
- pads = data->collect;
-
- GST_OBJECT_LOCK (pads);
- query_func = pads->priv->query_func;
- query_user_data = pads->priv->query_user_data;
- GST_OBJECT_UNLOCK (pads);
-
- if (GST_QUERY_IS_SERIALIZED (query)) {
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- need_unlock = TRUE;
- }
-
- if (G_LIKELY (query_func)) {
- res = query_func (pads, data, query, query_user_data);
- }
-
- if (need_unlock)
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
-
- unref_data (data);
- return res;
-
- /* ERRORS */
-pad_removed:
- {
- GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- return FALSE;
- }
-}
-
-
-/* For each buffer we receive we check if our collected condition is reached
- * and if so we call the collected function. When this is done we check if
- * data has been unqueued. If data is still queued we wait holding the stream
- * lock to make sure no EOS event can happen while we are ready to be
- * collected
- */
-static GstFlowReturn
-gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
-{
- GstCollectData *data;
- GstCollectPads *pads;
- GstFlowReturn ret;
- GstBuffer **buffer_p;
- guint32 cookie;
-
- GST_DEBUG ("Got buffer for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- /* some magic to get the managing collect_pads */
- GST_OBJECT_LOCK (pad);
- data = (GstCollectData *) gst_pad_get_element_private (pad);
- if (G_UNLIKELY (data == NULL))
- goto no_data;
- ref_data (data);
- GST_OBJECT_UNLOCK (pad);
-
- pads = data->collect;
-
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- /* if not started, bail out */
- if (G_UNLIKELY (!pads->priv->started))
- goto not_started;
- /* check if this pad is flushing */
- if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_FLUSHING)))
- goto flushing;
- /* pad was EOS, we can refuse this data */
- if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_EOS)))
- goto eos;
-
- /* see if we need to clip */
- if (pads->priv->clip_func) {
- GstBuffer *outbuf = NULL;
- ret =
- pads->priv->clip_func (pads, data, buffer, &outbuf,
- pads->priv->clip_user_data);
- buffer = outbuf;
-
- if (G_UNLIKELY (outbuf == NULL))
- goto clipped;
-
- if (G_UNLIKELY (ret == GST_FLOW_EOS))
- goto eos;
- else if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto error;
- }
-
- GST_DEBUG_OBJECT (pads, "Queuing buffer %p for pad %s:%s", buffer,
- GST_DEBUG_PAD_NAME (pad));
-
- /* One more pad has data queued */
- if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING))
- pads->priv->queuedpads++;
- buffer_p = &data->buffer;
- gst_buffer_replace (buffer_p, buffer);
-
- /* update segment last position if in TIME */
- if (G_LIKELY (data->segment.format == GST_FORMAT_TIME)) {
- GstClockTime timestamp;
-
- timestamp = GST_BUFFER_DTS_OR_PTS (buffer);
-
- if (GST_CLOCK_TIME_IS_VALID (timestamp))
- data->segment.position = timestamp;
- }
-
- /* While we have data queued on this pad try to collect stuff */
- do {
- /* Check if our collected condition is matched and call the collected
- * function if it is */
- ret = gst_collect_pads_check_collected (pads);
- /* when an error occurs, we want to report this back to the caller ASAP
- * without having to block if the buffer was not popped */
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto error;
-
- /* data was consumed, we can exit and accept new data */
- if (data->buffer == NULL)
- break;
-
- /* Having the _INIT here means we don't care about any broadcast up to here
- * (most of which occur with STREAM_LOCK held, so could not have happened
- * anyway). We do care about e.g. a remove initiated broadcast as of this
- * point. Putting it here also makes this thread ignores any evt it raised
- * itself (as is a usual WAIT semantic).
- */
- GST_COLLECT_PADS_EVT_INIT (cookie);
-
- /* pad could be removed and re-added */
- unref_data (data);
- GST_OBJECT_LOCK (pad);
- if (G_UNLIKELY ((data = gst_pad_get_element_private (pad)) == NULL))
- goto pad_removed;
- ref_data (data);
- GST_OBJECT_UNLOCK (pad);
-
- GST_DEBUG_OBJECT (pads, "Pad %s:%s has a buffer queued, waiting",
- GST_DEBUG_PAD_NAME (pad));
-
- /* wait to be collected, this must happen from another thread triggered
- * by the _chain function of another pad. We release the lock so we
- * can get stopped or flushed as well. We can however not get EOS
- * because we still hold the STREAM_LOCK.
- */
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- GST_COLLECT_PADS_EVT_WAIT (pads, cookie);
- GST_COLLECT_PADS_STREAM_LOCK (pads);
-
- GST_DEBUG_OBJECT (pads, "Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad));
-
- /* after a signal, we could be stopped */
- if (G_UNLIKELY (!pads->priv->started))
- goto not_started;
- /* check if this pad is flushing */
- if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data,
- GST_COLLECT_PADS_STATE_FLUSHING)))
- goto flushing;
- }
- while (data->buffer != NULL);
-
-unlock_done:
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- /* data is definitely NULL if pad_removed goto was run. */
- if (data)
- unref_data (data);
- if (buffer)
- gst_buffer_unref (buffer);
- return ret;
-
-pad_removed:
- {
- GST_WARNING ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- ret = GST_FLOW_NOT_LINKED;
- goto unlock_done;
- }
- /* ERRORS */
-no_data:
- {
- GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- gst_buffer_unref (buffer);
- return GST_FLOW_NOT_LINKED;
- }
-not_started:
- {
- GST_DEBUG ("not started");
- gst_collect_pads_clear (pads, data);
- ret = GST_FLOW_FLUSHING;
- goto unlock_done;
- }
-flushing:
- {
- GST_DEBUG ("pad %s:%s is flushing", GST_DEBUG_PAD_NAME (pad));
- gst_collect_pads_clear (pads, data);
- ret = GST_FLOW_FLUSHING;
- goto unlock_done;
- }
-eos:
- {
- /* we should not post an error for this, just inform upstream that
- * we don't expect anything anymore */
- GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad));
- ret = GST_FLOW_EOS;
- goto unlock_done;
- }
-clipped:
- {
- GST_DEBUG ("clipped buffer on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- ret = GST_FLOW_OK;
- goto unlock_done;
- }
-error:
- {
- /* we print the error, the element should post a reasonable error
- * message for fatal errors */
- GST_DEBUG ("collect failed, reason %d (%s)", ret, gst_flow_get_name (ret));
- gst_collect_pads_clear (pads, data);
- goto unlock_done;
- }
-}
diff --git a/libs/gst/base/gstcollectpads.h b/libs/gst/base/gstcollectpads.h
deleted file mode 100644
index 13d60a17d9..0000000000
--- a/libs/gst/base/gstcollectpads.h
+++ /dev/null
@@ -1,456 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sourceforge.net>
- *
- * gstcollectpads.h:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_COLLECT_PADS_H__
-#define __GST_COLLECT_PADS_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.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(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECT_PADS))
-
-typedef struct _GstCollectData GstCollectData;
-typedef struct _GstCollectDataPrivate GstCollectDataPrivate;
-typedef struct _GstCollectPads GstCollectPads;
-typedef struct _GstCollectPadsPrivate GstCollectPadsPrivate;
-typedef struct _GstCollectPadsClass GstCollectPadsClass;
-
-/**
- * GstCollectDataDestroyNotify:
- * @data: the #GstCollectData that will be freed
- *
- * A function that will be called when the #GstCollectData will be freed.
- * It is passed the pointer to the structure and should free any custom
- * memory and resources allocated for it.
- */
-typedef void (*GstCollectDataDestroyNotify) (GstCollectData *data);
-
-/**
- * GstCollectPadsStateFlags:
- * @GST_COLLECT_PADS_STATE_EOS: Set if collectdata's pad is EOS.
- * @GST_COLLECT_PADS_STATE_FLUSHING: Set if collectdata's pad is flushing.
- * @GST_COLLECT_PADS_STATE_NEW_SEGMENT: Set if collectdata's pad received a
- * new_segment event.
- * @GST_COLLECT_PADS_STATE_WAITING: Set if collectdata's pad must be waited
- * for when collecting.
- * @GST_COLLECT_PADS_STATE_LOCKED: Set collectdata's pad WAITING state must
- * not be changed.
- * #GstCollectPadsStateFlags indicate private state of a collectdata('s pad).
- */
-typedef enum {
- GST_COLLECT_PADS_STATE_EOS = 1 << 0,
- GST_COLLECT_PADS_STATE_FLUSHING = 1 << 1,
- GST_COLLECT_PADS_STATE_NEW_SEGMENT = 1 << 2,
- GST_COLLECT_PADS_STATE_WAITING = 1 << 3,
- GST_COLLECT_PADS_STATE_LOCKED = 1 << 4
-} GstCollectPadsStateFlags;
-
-/**
- * GST_COLLECT_PADS_STATE:
- * @data: a #GstCollectData.
- *
- * A flags word containing #GstCollectPadsStateFlags flags set
- * on this collected pad.
- */
-#define GST_COLLECT_PADS_STATE(data) (((GstCollectData *) data)->state)
-/**
- * GST_COLLECT_PADS_STATE_IS_SET:
- * @data: a #GstCollectData.
- * @flag: the #GstCollectPadsStateFlags to check.
- *
- * Gives the status of a specific flag on a collected pad.
- */
-#define GST_COLLECT_PADS_STATE_IS_SET(data,flag) !!(GST_COLLECT_PADS_STATE (data) & flag)
-/**
- * GST_COLLECT_PADS_STATE_SET:
- * @data: a #GstCollectData.
- * @flag: the #GstCollectPadsStateFlags to set.
- *
- * Sets a state flag on a collected pad.
- */
-#define GST_COLLECT_PADS_STATE_SET(data,flag) (GST_COLLECT_PADS_STATE (data) |= flag)
-/**
- * GST_COLLECT_PADS_STATE_UNSET:
- * @data: a #GstCollectData.
- * @flag: the #GstCollectPadsStateFlags to clear.
- *
- * Clears a state flag on a collected pad.
- */
-#define GST_COLLECT_PADS_STATE_UNSET(data,flag) (GST_COLLECT_PADS_STATE (data) &= ~(flag))
-
-/**
- * GST_COLLECT_PADS_DTS:
- * @data: A #GstCollectData.
- *
- * Returns the DTS that has been converted to running time when using
- * gst_collect_pads_clip_running_time(). Unlike the value saved into
- * the buffer, this value is of type gint64 and may be negative. This allow
- * properly handling streams with frame reordering where the first DTS may
- * be negative. If the initial DTS was not set, this value will be
- * set to %G_MININT64.
- *
- * Since: 1.6
- */
-#define GST_COLLECT_PADS_DTS(data) (((GstCollectData *) data)->ABI.abi.dts)
-
-/**
- * GST_COLLECT_PADS_DTS_IS_VALID:
- * @data: A #GstCollectData.
- *
- * Check if running DTS value store is valid.
- *
- * Since: 1.6
- */
-#define GST_COLLECT_PADS_DTS_IS_VALID(data) (GST_CLOCK_STIME_IS_VALID (GST_COLLECT_PADS_DTS (data)))
-
-/**
- * GstCollectData:
- * @collect: owner #GstCollectPads
- * @pad: #GstPad managed by this data
- * @buffer: currently queued buffer.
- * @pos: position in the buffer
- * @segment: last segment received.
- * @dts: the signed version of the DTS converted to running time. To access
- * this member, use %GST_COLLECT_PADS_DTS macro. (Since: 1.6)
- *
- * Structure used by the collect_pads.
- */
-struct _GstCollectData
-{
- /* with STREAM_LOCK of @collect */
- GstCollectPads *collect;
- GstPad *pad;
- GstBuffer *buffer;
- guint pos;
- GstSegment segment;
-
- /*< private >*/
- /* state: bitfield for easier extension;
- * eos, flushing, new_segment, waiting */
- GstCollectPadsStateFlags state;
-
- GstCollectDataPrivate *priv;
-
- union {
- struct {
- /*< public >*/
- gint64 dts;
- /*< private >*/
- } abi;
- gpointer _gst_reserved[GST_PADDING];
- } ABI;
-};
-
-/**
- * GstCollectPadsFunction:
- * @pads: the #GstCollectPads that triggered 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);
-
-/**
- * GstCollectPadsBufferFunction:
- * @pads: the #GstCollectPads that triggered the callback
- * @data: the #GstCollectData of pad that has received the buffer
- * @buffer: (transfer full): the #GstBuffer
- * @user_data: user data passed to gst_collect_pads_set_buffer_function()
- *
- * A function that will be called when a (considered oldest) buffer can be muxed.
- * If all pads have reached EOS, this function is called with %NULL @buffer
- * and %NULL @data.
- *
- * Returns: %GST_FLOW_OK for success
- */
-typedef GstFlowReturn (*GstCollectPadsBufferFunction) (GstCollectPads *pads, GstCollectData *data,
- GstBuffer *buffer, gpointer user_data);
-
-/**
- * GstCollectPadsCompareFunction:
- * @pads: the #GstCollectPads that is comparing the timestamps
- * @data1: the first #GstCollectData
- * @timestamp1: the first timestamp
- * @data2: the second #GstCollectData
- * @timestamp2: the second timestamp
- * @user_data: user data passed to gst_collect_pads_set_compare_function()
- *
- * A function for comparing two timestamps of buffers or newsegments collected on one pad.
- *
- * Returns: Integer less than zero when first timestamp is deemed older than the second one.
- * Zero if the timestamps are deemed equally old.
- * Integer greater than zero when second timestamp is deemed older than the first one.
- */
-typedef gint (*GstCollectPadsCompareFunction) (GstCollectPads *pads,
- GstCollectData * data1, GstClockTime timestamp1,
- GstCollectData * data2, GstClockTime timestamp2,
- gpointer user_data);
-
-/**
- * GstCollectPadsEventFunction:
- * @pads: the #GstCollectPads that triggered the callback
- * @pad: the #GstPad that received an event
- * @event: the #GstEvent received
- * @user_data: user data passed to gst_collect_pads_set_event_function()
- *
- * A function that will be called while processing an event. It takes
- * ownership of the event and is responsible for chaining up (to
- * gst_collect_pads_event_default()) or dropping events (such typical cases
- * being handled by the default handler).
- *
- * Returns: %TRUE if the pad could handle the event
- */
-typedef gboolean (*GstCollectPadsEventFunction) (GstCollectPads *pads, GstCollectData * pad,
- GstEvent * event, gpointer user_data);
-
-
-/**
- * GstCollectPadsQueryFunction:
- * @pads: the #GstCollectPads that triggered the callback
- * @pad: the #GstPad that received an event
- * @query: the #GstEvent received
- * @user_data: user data passed to gst_collect_pads_set_query_function()
- *
- * A function that will be called while processing a query. It takes
- * ownership of the query and is responsible for chaining up (to
- * events downstream (with gst_pad_event_default()).
- *
- * Returns: %TRUE if the pad could handle the event
- */
-typedef gboolean (*GstCollectPadsQueryFunction) (GstCollectPads *pads, GstCollectData * pad,
- GstQuery * query, gpointer user_data);
-
-/**
- * GstCollectPadsClipFunction:
- * @pads: a #GstCollectPads
- * @data: a #GstCollectData
- * @inbuffer: (transfer full): the input #GstBuffer
- * @outbuffer: (out): the output #GstBuffer
- * @user_data: user data
- *
- * A function that will be called when @inbuffer is received on the pad managed
- * by @data in the collectpad object @pads.
- *
- * The function should use the segment of @data and the negotiated media type on
- * the pad to perform clipping of @inbuffer.
- *
- * This function takes ownership of @inbuffer and should output a buffer in
- * @outbuffer or return %NULL in @outbuffer if the buffer should be dropped.
- *
- * Returns: a #GstFlowReturn that corresponds to the result of clipping.
- */
-typedef GstFlowReturn (*GstCollectPadsClipFunction) (GstCollectPads *pads, GstCollectData *data,
- GstBuffer *inbuffer, GstBuffer **outbuffer,
- gpointer user_data);
-
-
-/**
- * GstCollectPadsFlushFunction:
- * @pads: a #GstCollectPads
- * @user_data: user data
- *
- * A function that will be called while processing a flushing seek event.
- *
- * The function should flush any internal state of the element and the state of
- * all the pads. It should clear only the state not directly managed by the
- * @pads object. It is therefore not necessary to call
- * gst_collect_pads_set_flushing nor gst_collect_pads_clear from this function.
- *
- * Since: 1.4
- */
-typedef void (*GstCollectPadsFlushFunction) (GstCollectPads *pads, gpointer user_data);
-
-/**
- * GST_COLLECT_PADS_GET_STREAM_LOCK:
- * @pads: a #GstCollectPads
- *
- * Get the stream lock of @pads. The stream lock is used to coordinate and
- * serialize execution among the various streams being collected, and in
- * protecting the resources used to accomplish this.
- */
-#define GST_COLLECT_PADS_GET_STREAM_LOCK(pads) (&((GstCollectPads *)pads)->stream_lock)
-/**
- * GST_COLLECT_PADS_STREAM_LOCK:
- * @pads: a #GstCollectPads
- *
- * Lock the stream lock of @pads.
- */
-#define GST_COLLECT_PADS_STREAM_LOCK(pads) g_rec_mutex_lock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads))
-/**
- * GST_COLLECT_PADS_STREAM_UNLOCK:
- * @pads: a #GstCollectPads
- *
- * Unlock the stream lock of @pads.
- */
-#define GST_COLLECT_PADS_STREAM_UNLOCK(pads) g_rec_mutex_unlock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads))
-
-/**
- * GstCollectPads:
- * @data: (element-type GstBase.CollectData): #GList of #GstCollectData managed
- * by this #GstCollectPads.
- *
- * Collectpads object.
- */
-struct _GstCollectPads {
- GstObject object;
-
- /*< public >*/ /* with LOCK and/or STREAM_LOCK */
- GSList *data; /* list of CollectData items */
-
- /*< private >*/
- GRecMutex stream_lock; /* used to serialize collection among several streams */
-
- GstCollectPadsPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstCollectPadsClass {
- GstObjectClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_BASE_API
-GType gst_collect_pads_get_type (void);
-
-/* creating the object */
-
-GST_BASE_API
-GstCollectPads* gst_collect_pads_new (void);
-
-/* set the callbacks */
-
-GST_BASE_API
-void gst_collect_pads_set_function (GstCollectPads *pads,
- GstCollectPadsFunction func,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_buffer_function (GstCollectPads *pads,
- GstCollectPadsBufferFunction func,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_event_function (GstCollectPads *pads,
- GstCollectPadsEventFunction func,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_query_function (GstCollectPads *pads,
- GstCollectPadsQueryFunction func,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_compare_function (GstCollectPads *pads,
- GstCollectPadsCompareFunction func,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_clip_function (GstCollectPads *pads,
- GstCollectPadsClipFunction clipfunc,
- gpointer user_data);
-GST_BASE_API
-void gst_collect_pads_set_flush_function (GstCollectPads *pads,
- GstCollectPadsFlushFunction func,
- gpointer user_data);
-
-/* pad management */
-
-GST_BASE_API
-GstCollectData* gst_collect_pads_add_pad (GstCollectPads *pads, GstPad *pad, guint size,
- GstCollectDataDestroyNotify destroy_notify,
- gboolean lock);
-GST_BASE_API
-gboolean gst_collect_pads_remove_pad (GstCollectPads *pads, GstPad *pad);
-
-/* start/stop collection */
-
-GST_BASE_API
-void gst_collect_pads_start (GstCollectPads *pads);
-
-GST_BASE_API
-void gst_collect_pads_stop (GstCollectPads *pads);
-
-GST_BASE_API
-void gst_collect_pads_set_flushing (GstCollectPads *pads, gboolean flushing);
-
-/* get collected buffers */
-
-GST_BASE_API
-GstBuffer* gst_collect_pads_peek (GstCollectPads *pads, GstCollectData *data);
-
-GST_BASE_API
-GstBuffer* gst_collect_pads_pop (GstCollectPads *pads, GstCollectData *data);
-
-/* get collected bytes */
-
-GST_BASE_API
-guint gst_collect_pads_available (GstCollectPads *pads);
-
-GST_BASE_API
-guint gst_collect_pads_flush (GstCollectPads *pads, GstCollectData *data,
- guint size);
-GST_BASE_API
-GstBuffer* gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
- guint size);
-GST_BASE_API
-GstBuffer* gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data,
- guint size);
-
-/* setting and unsetting waiting mode */
-
-GST_BASE_API
-void gst_collect_pads_set_waiting (GstCollectPads *pads, GstCollectData *data,
- gboolean waiting);
-
-/* convenience helper */
-
-GST_BASE_API
-GstFlowReturn gst_collect_pads_clip_running_time (GstCollectPads * pads,
- GstCollectData * cdata,
- GstBuffer * buf, GstBuffer ** outbuf,
- gpointer user_data);
-
-/* default handlers */
-
-GST_BASE_API
-gboolean gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data,
- GstEvent * event, gboolean discard);
-GST_BASE_API
-gboolean gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad,
- GstEvent * event);
-GST_BASE_API
-gboolean gst_collect_pads_query_default (GstCollectPads * pads, GstCollectData * data,
- GstQuery * query, gboolean discard);
-
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCollectPads, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_COLLECT_PADS_H__ */
diff --git a/libs/gst/base/gstdataqueue.c b/libs/gst/base/gstdataqueue.c
deleted file mode 100644
index ac93b8e346..0000000000
--- a/libs/gst/base/gstdataqueue.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
- *
- * gstdataqueue.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstdataqueue
- * @title: GstDataQueue
- * @short_description: Threadsafe queueing object
- *
- * #GstDataQueue is an object that handles threadsafe queueing of objects. It
- * also provides size-related functionality. This object should be used for
- * any #GstElement that wishes to provide some sort of queueing functionality.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include "string.h"
-#include "gstdataqueue.h"
-#include "gstqueuearray.h"
-#include "gst/glib-compat-private.h"
-
-GST_DEBUG_CATEGORY_STATIC (data_queue_debug);
-#define GST_CAT_DEFAULT (data_queue_debug)
-GST_DEBUG_CATEGORY_STATIC (data_queue_dataflow);
-
-
-/* Queue signals and args */
-enum
-{
- SIGNAL_EMPTY,
- SIGNAL_FULL,
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_CUR_LEVEL_VISIBLE,
- PROP_CUR_LEVEL_BYTES,
- PROP_CUR_LEVEL_TIME
- /* FILL ME */
-};
-
-struct _GstDataQueuePrivate
-{
- /* the array of data we're keeping our grubby hands on */
- GstQueueArray *queue;
-
- GstDataQueueSize cur_level; /* size of the queue */
- GstDataQueueCheckFullFunction checkfull; /* Callback to check if the queue is full */
- gpointer *checkdata;
-
- GMutex qlock; /* lock for queue (vs object lock) */
- gboolean waiting_add;
- GCond item_add; /* signals buffers now available for reading */
- gboolean waiting_del;
- GCond item_del; /* signals space now available for writing */
- gboolean flushing; /* indicates whether conditions where signalled because
- * of external flushing */
- GstDataQueueFullCallback fullcallback;
- GstDataQueueEmptyCallback emptycallback;
-};
-
-#define GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \
- GST_CAT_TRACE (data_queue_dataflow, \
- "locking qlock from thread %p", \
- g_thread_self ()); \
- g_mutex_lock (&q->priv->qlock); \
- GST_CAT_TRACE (data_queue_dataflow, \
- "locked qlock from thread %p", \
- g_thread_self ()); \
-} G_STMT_END
-
-#define GST_DATA_QUEUE_MUTEX_LOCK_CHECK(q, label) G_STMT_START { \
- GST_DATA_QUEUE_MUTEX_LOCK (q); \
- if (q->priv->flushing) \
- goto label; \
- } G_STMT_END
-
-#define GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \
- GST_CAT_TRACE (data_queue_dataflow, \
- "unlocking qlock from thread %p", \
- g_thread_self ()); \
- g_mutex_unlock (&q->priv->qlock); \
-} G_STMT_END
-
-#define STATUS(q, msg) \
- GST_CAT_LOG (data_queue_dataflow, \
- "queue:%p " msg ": %u visible items, %u " \
- "bytes, %"G_GUINT64_FORMAT \
- " ns, %u elements", \
- queue, \
- q->priv->cur_level.visible, \
- q->priv->cur_level.bytes, \
- q->priv->cur_level.time, \
- gst_queue_array_get_length (q->priv->queue))
-
-static void gst_data_queue_finalize (GObject * object);
-
-static void gst_data_queue_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_data_queue_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-static guint gst_data_queue_signals[LAST_SIGNAL] = { 0 };
-
-#define _do_init \
-{ \
- GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0, \
- "data queue object"); \
- GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0, \
- "dataflow inside the data queue object"); \
-}
-
-#define parent_class gst_data_queue_parent_class
-G_DEFINE_TYPE_WITH_CODE (GstDataQueue, gst_data_queue, G_TYPE_OBJECT,
- G_ADD_PRIVATE (GstDataQueue) _do_init);
-
-static void
-gst_data_queue_class_init (GstDataQueueClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->set_property = gst_data_queue_set_property;
- gobject_class->get_property = gst_data_queue_get_property;
-
- /* signals */
- /**
- * GstDataQueue::empty: (skip)
- * @queue: the queue instance
- *
- * Reports that the queue became empty (empty).
- * A queue is empty if the total amount of visible items inside it (num-visible, time,
- * size) is lower than the boundary values which can be set through the GObject
- * properties.
- */
- gst_data_queue_signals[SIGNAL_EMPTY] =
- g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GstDataQueueClass, empty), NULL, NULL,
- NULL, G_TYPE_NONE, 0);
-
- /**
- * GstDataQueue::full: (skip)
- * @queue: the queue instance
- *
- * Reports that the queue became full (full).
- * A queue is full if the total amount of data inside it (num-visible, time,
- * size) is higher than the boundary values which can be set through the GObject
- * properties.
- */
- gst_data_queue_signals[SIGNAL_FULL] =
- g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GstDataQueueClass, full), NULL, NULL,
- NULL, G_TYPE_NONE, 0);
-
- /* properties */
- g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
- g_param_spec_uint ("current-level-bytes", "Current level (kB)",
- "Current amount of data in the queue (bytes)",
- 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_VISIBLE,
- g_param_spec_uint ("current-level-visible",
- "Current level (visible items)",
- "Current number of visible items in the queue", 0, G_MAXUINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME,
- g_param_spec_uint64 ("current-level-time", "Current level (ns)",
- "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- gobject_class->finalize = gst_data_queue_finalize;
-}
-
-static void
-gst_data_queue_init (GstDataQueue * queue)
-{
- queue->priv = gst_data_queue_get_instance_private (queue);
-
- queue->priv->cur_level.visible = 0; /* no content */
- queue->priv->cur_level.bytes = 0; /* no content */
- queue->priv->cur_level.time = 0; /* no content */
-
- queue->priv->checkfull = NULL;
-
- g_mutex_init (&queue->priv->qlock);
- g_cond_init (&queue->priv->item_add);
- g_cond_init (&queue->priv->item_del);
- queue->priv->queue = gst_queue_array_new (50);
-
- GST_DEBUG ("initialized queue's not_empty & not_full conditions");
-}
-
-/**
- * gst_data_queue_new: (skip)
- * @checkfull: the callback used to tell if the element considers the queue full
- * or not.
- * @fullcallback: the callback which will be called when the queue is considered full.
- * @emptycallback: the callback which will be called when the queue is considered empty.
- * @checkdata: a #gpointer that will be passed to the @checkfull, @fullcallback,
- * and @emptycallback callbacks.
- *
- * Creates a new #GstDataQueue. If @fullcallback or @emptycallback are supplied, then
- * the #GstDataQueue will call the respective callback to signal full or empty condition.
- * If the callbacks are NULL the #GstDataQueue will instead emit 'full' and 'empty'
- * signals.
- *
- * Returns: a new #GstDataQueue.
- *
- * Since: 1.2
- */
-GstDataQueue *
-gst_data_queue_new (GstDataQueueCheckFullFunction checkfull,
- GstDataQueueFullCallback fullcallback,
- GstDataQueueEmptyCallback emptycallback, gpointer checkdata)
-{
- GstDataQueue *ret;
-
- g_return_val_if_fail (checkfull != NULL, NULL);
-
- ret = g_object_new (GST_TYPE_DATA_QUEUE, NULL);
- ret->priv->checkfull = checkfull;
- ret->priv->checkdata = checkdata;
- ret->priv->fullcallback = fullcallback;
- ret->priv->emptycallback = emptycallback;
-
- return ret;
-}
-
-static void
-gst_data_queue_cleanup (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- while (!gst_queue_array_is_empty (priv->queue)) {
- GstDataQueueItem *item = gst_queue_array_pop_head (priv->queue);
-
- /* Just call the destroy notify on the item */
- item->destroy (item);
- }
- priv->cur_level.visible = 0;
- priv->cur_level.bytes = 0;
- priv->cur_level.time = 0;
-}
-
-/* called only once, as opposed to dispose */
-static void
-gst_data_queue_finalize (GObject * object)
-{
- GstDataQueue *queue = GST_DATA_QUEUE (object);
- GstDataQueuePrivate *priv = queue->priv;
-
- GST_DEBUG ("finalizing queue");
-
- gst_data_queue_cleanup (queue);
- gst_queue_array_free (priv->queue);
-
- GST_DEBUG ("free mutex");
- g_mutex_clear (&priv->qlock);
- GST_DEBUG ("done free mutex");
-
- g_cond_clear (&priv->item_add);
- g_cond_clear (&priv->item_del);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static inline void
-gst_data_queue_locked_flush (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- STATUS (queue, "before flushing");
- gst_data_queue_cleanup (queue);
- STATUS (queue, "after flushing");
- /* we deleted something... */
- if (priv->waiting_del)
- g_cond_signal (&priv->item_del);
-}
-
-static inline gboolean
-gst_data_queue_locked_is_empty (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- return (gst_queue_array_get_length (priv->queue) == 0);
-}
-
-static inline gboolean
-gst_data_queue_locked_is_full (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- return priv->checkfull (queue, priv->cur_level.visible,
- priv->cur_level.bytes, priv->cur_level.time, priv->checkdata);
-}
-
-/**
- * gst_data_queue_flush: (skip)
- * @queue: a #GstDataQueue.
- *
- * Flushes all the contents of the @queue. Any call to #gst_data_queue_push and
- * #gst_data_queue_pop will be released.
- * MT safe.
- *
- * Since: 1.2
- */
-void
-gst_data_queue_flush (GstDataQueue * queue)
-{
- GST_DEBUG ("queue:%p", queue);
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- gst_data_queue_locked_flush (queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-}
-
-/**
- * gst_data_queue_is_empty: (skip)
- * @queue: a #GstDataQueue.
- *
- * Queries if there are any items in the @queue.
- * MT safe.
- *
- * Returns: %TRUE if @queue is empty.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_is_empty (GstDataQueue * queue)
-{
- gboolean res;
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- res = gst_data_queue_locked_is_empty (queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return res;
-}
-
-/**
- * gst_data_queue_is_full: (skip)
- * @queue: a #GstDataQueue.
- *
- * Queries if @queue is full. This check will be done using the
- * #GstDataQueueCheckFullFunction registered with @queue.
- * MT safe.
- *
- * Returns: %TRUE if @queue is full.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_is_full (GstDataQueue * queue)
-{
- gboolean res;
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- res = gst_data_queue_locked_is_full (queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return res;
-}
-
-/**
- * gst_data_queue_set_flushing: (skip)
- * @queue: a #GstDataQueue.
- * @flushing: a #gboolean stating if the queue will be flushing or not.
- *
- * Sets the queue to flushing state if @flushing is %TRUE. If set to flushing
- * state, any incoming data on the @queue will be discarded. Any call currently
- * blocking on #gst_data_queue_push or #gst_data_queue_pop will return straight
- * away with a return value of %FALSE. While the @queue is in flushing state,
- * all calls to those two functions will return %FALSE.
- *
- * MT Safe.
- *
- * Since: 1.2
- */
-void
-gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- GST_DEBUG ("queue:%p , flushing:%d", queue, flushing);
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- priv->flushing = flushing;
- if (flushing) {
- /* release push/pop functions */
- if (priv->waiting_add)
- g_cond_signal (&priv->item_add);
- if (priv->waiting_del)
- g_cond_signal (&priv->item_del);
- }
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-}
-
-static void
-gst_data_queue_push_force_unlocked (GstDataQueue * queue,
- GstDataQueueItem * item)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- gst_queue_array_push_tail (priv->queue, item);
-
- if (item->visible)
- priv->cur_level.visible++;
- priv->cur_level.bytes += item->size;
- priv->cur_level.time += item->duration;
-}
-
-/**
- * gst_data_queue_push_force: (skip)
- * @queue: a #GstDataQueue.
- * @item: a #GstDataQueueItem.
- *
- * Pushes a #GstDataQueueItem (or a structure that begins with the same fields)
- * on the @queue. It ignores if the @queue is full or not and forces the @item
- * to be pushed anyway.
- * MT safe.
- *
- * Note that this function has slightly different semantics than gst_pad_push()
- * and gst_pad_push_event(): this function only takes ownership of @item and
- * the #GstMiniObject contained in @item if the push was successful. If %FALSE
- * is returned, the caller is responsible for freeing @item and its contents.
- *
- * Returns: %TRUE if the @item was successfully pushed on the @queue.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
- g_return_val_if_fail (item != NULL, FALSE);
-
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- STATUS (queue, "before pushing");
- gst_data_queue_push_force_unlocked (queue, item);
- STATUS (queue, "after pushing");
- if (priv->waiting_add)
- g_cond_signal (&priv->item_add);
-
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return TRUE;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG ("queue:%p, we are flushing", queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- return FALSE;
- }
-}
-
-/**
- * gst_data_queue_push: (skip)
- * @queue: a #GstDataQueue.
- * @item: a #GstDataQueueItem.
- *
- * Pushes a #GstDataQueueItem (or a structure that begins with the same fields)
- * on the @queue. If the @queue is full, the call will block until space is
- * available, OR the @queue is set to flushing state.
- * MT safe.
- *
- * Note that this function has slightly different semantics than gst_pad_push()
- * and gst_pad_push_event(): this function only takes ownership of @item and
- * the #GstMiniObject contained in @item if the push was successful. If %FALSE
- * is returned, the caller is responsible for freeing @item and its contents.
- *
- * Returns: %TRUE if the @item was successfully pushed on the @queue.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
- g_return_val_if_fail (item != NULL, FALSE);
-
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- STATUS (queue, "before pushing");
-
- /* We ALWAYS need to check for queue fillness */
- if (gst_data_queue_locked_is_full (queue)) {
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- if (G_LIKELY (priv->fullcallback))
- priv->fullcallback (queue, priv->checkdata);
- else
- g_signal_emit (queue, gst_data_queue_signals[SIGNAL_FULL], 0);
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- /* signal might have removed some items */
- while (gst_data_queue_locked_is_full (queue)) {
- priv->waiting_del = TRUE;
- g_cond_wait (&priv->item_del, &priv->qlock);
- priv->waiting_del = FALSE;
- if (priv->flushing)
- goto flushing;
- }
- }
-
- gst_data_queue_push_force_unlocked (queue, item);
-
- STATUS (queue, "after pushing");
- if (priv->waiting_add)
- g_cond_signal (&priv->item_add);
-
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return TRUE;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG ("queue:%p, we are flushing", queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- return FALSE;
- }
-}
-
-static gboolean
-_gst_data_queue_wait_non_empty (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- while (gst_data_queue_locked_is_empty (queue)) {
- priv->waiting_add = TRUE;
- g_cond_wait (&priv->item_add, &priv->qlock);
- priv->waiting_add = FALSE;
- if (priv->flushing)
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * gst_data_queue_pop: (skip)
- * @queue: a #GstDataQueue.
- * @item: (out): pointer to store the returned #GstDataQueueItem.
- *
- * Retrieves the first @item available on the @queue. If the queue is currently
- * empty, the call will block until at least one item is available, OR the
- * @queue is set to the flushing state.
- * MT safe.
- *
- * Returns: %TRUE if an @item was successfully retrieved from the @queue.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
- g_return_val_if_fail (item != NULL, FALSE);
-
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- STATUS (queue, "before popping");
-
- if (gst_data_queue_locked_is_empty (queue)) {
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- if (G_LIKELY (priv->emptycallback))
- priv->emptycallback (queue, priv->checkdata);
- else
- g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0);
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- if (!_gst_data_queue_wait_non_empty (queue))
- goto flushing;
- }
-
- /* Get the item from the GQueue */
- *item = gst_queue_array_pop_head (priv->queue);
-
- /* update current level counter */
- if ((*item)->visible)
- priv->cur_level.visible--;
- priv->cur_level.bytes -= (*item)->size;
- priv->cur_level.time -= (*item)->duration;
-
- STATUS (queue, "after popping");
- if (priv->waiting_del)
- g_cond_signal (&priv->item_del);
-
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return TRUE;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG ("queue:%p, we are flushing", queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- return FALSE;
- }
-}
-
-static gint
-is_of_type (gconstpointer a, gconstpointer b)
-{
- return !G_TYPE_CHECK_INSTANCE_TYPE (a, GPOINTER_TO_SIZE (b));
-}
-
-/**
- * gst_data_queue_peek: (skip)
- * @queue: a #GstDataQueue.
- * @item: (out): pointer to store the returned #GstDataQueueItem.
- *
- * Retrieves the first @item available on the @queue without removing it.
- * If the queue is currently empty, the call will block until at least
- * one item is available, OR the @queue is set to the flushing state.
- * MT safe.
- *
- * Returns: %TRUE if an @item was successfully retrieved from the @queue.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
- g_return_val_if_fail (item != NULL, FALSE);
-
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- STATUS (queue, "before peeking");
-
- if (gst_data_queue_locked_is_empty (queue)) {
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- if (G_LIKELY (priv->emptycallback))
- priv->emptycallback (queue, priv->checkdata);
- else
- g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0);
- GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
-
- if (!_gst_data_queue_wait_non_empty (queue))
- goto flushing;
- }
-
- /* Get the item from the GQueue */
- *item = gst_queue_array_peek_head (priv->queue);
-
- STATUS (queue, "after peeking");
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- return TRUE;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG ("queue:%p, we are flushing", queue);
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
- return FALSE;
- }
-}
-
-/**
- * gst_data_queue_drop_head: (skip)
- * @queue: The #GstDataQueue to drop an item from.
- * @type: The #GType of the item to drop.
- *
- * Pop and unref the head-most #GstMiniObject with the given #GType.
- *
- * Returns: %TRUE if an element was removed.
- *
- * Since: 1.2
- */
-gboolean
-gst_data_queue_drop_head (GstDataQueue * queue, GType type)
-{
- gboolean res = FALSE;
- GstDataQueueItem *leak = NULL;
- guint idx;
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
-
- GST_DEBUG ("queue:%p", queue);
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- idx = gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type));
-
- if (idx == -1)
- goto done;
-
- leak = gst_queue_array_drop_element (priv->queue, idx);
-
- if (leak->visible)
- priv->cur_level.visible--;
- priv->cur_level.bytes -= leak->size;
- priv->cur_level.time -= leak->duration;
-
- leak->destroy (leak);
-
- res = TRUE;
-
-done:
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-
- GST_DEBUG ("queue:%p , res:%d", queue, res);
-
- return res;
-}
-
-/**
- * gst_data_queue_limits_changed: (skip)
- * @queue: The #GstDataQueue
- *
- * Inform the queue that the limits for the fullness check have changed and that
- * any blocking gst_data_queue_push() should be unblocked to recheck the limits.
- *
- * Since: 1.2
- */
-void
-gst_data_queue_limits_changed (GstDataQueue * queue)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- g_return_if_fail (GST_IS_DATA_QUEUE (queue));
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
- if (priv->waiting_del) {
- GST_DEBUG ("signal del");
- g_cond_signal (&priv->item_del);
- }
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-}
-
-/**
- * gst_data_queue_get_level: (skip)
- * @queue: The #GstDataQueue
- * @level: (out): the location to store the result
- *
- * Get the current level of the queue.
- *
- * Since: 1.2
- */
-void
-gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level)
-{
- GstDataQueuePrivate *priv = queue->priv;
-
- memcpy (level, (&priv->cur_level), sizeof (GstDataQueueSize));
-}
-
-static void
-gst_data_queue_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- switch (prop_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_data_queue_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstDataQueue *queue = GST_DATA_QUEUE (object);
- GstDataQueuePrivate *priv = queue->priv;
-
- GST_DATA_QUEUE_MUTEX_LOCK (queue);
-
- switch (prop_id) {
- case PROP_CUR_LEVEL_BYTES:
- g_value_set_uint (value, priv->cur_level.bytes);
- break;
- case PROP_CUR_LEVEL_VISIBLE:
- g_value_set_uint (value, priv->cur_level.visible);
- break;
- case PROP_CUR_LEVEL_TIME:
- g_value_set_uint64 (value, priv->cur_level.time);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
-}
diff --git a/libs/gst/base/gstdataqueue.h b/libs/gst/base/gstdataqueue.h
deleted file mode 100644
index e814a2b693..0000000000
--- a/libs/gst/base/gstdataqueue.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
- *
- * gstdataqueue.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_DATA_QUEUE_H__
-#define __GST_DATA_QUEUE_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-#define GST_TYPE_DATA_QUEUE \
- (gst_data_queue_get_type())
-#define GST_DATA_QUEUE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DATA_QUEUE,GstDataQueue))
-#define GST_DATA_QUEUE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DATA_QUEUE,GstDataQueueClass))
-#define GST_IS_DATA_QUEUE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DATA_QUEUE))
-#define GST_IS_DATA_QUEUE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DATA_QUEUE))
-
-typedef struct _GstDataQueue GstDataQueue;
-typedef struct _GstDataQueueClass GstDataQueueClass;
-typedef struct _GstDataQueueSize GstDataQueueSize;
-typedef struct _GstDataQueueItem GstDataQueueItem;
-typedef struct _GstDataQueuePrivate GstDataQueuePrivate;
-
-/**
- * GstDataQueueItem: (skip)
- * @object: the #GstMiniObject to queue.
- * @size: the size in bytes of the miniobject.
- * @duration: the duration in #GstClockTime of the miniobject. Can not be
- * %GST_CLOCK_TIME_NONE.
- * @visible: %TRUE if @object should be considered as a visible object.
- * @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem.
- * This function should also drop the reference to @object the owner of the
- * #GstDataQueueItem is assumed to hold.
- *
- * Structure used by #GstDataQueue. You can supply a different structure, as
- * long as the top of the structure is identical to this structure.
- */
-
-struct _GstDataQueueItem
-{
- GstMiniObject *object;
- guint size;
- guint64 duration;
- gboolean visible;
-
- /* user supplied destroy function */
- GDestroyNotify destroy;
-
- /* < private > */
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstDataQueueSize: (skip)
- * @visible: number of buffers
- * @bytes: number of bytes
- * @time: amount of time
- *
- * Structure describing the size of a queue.
- */
-struct _GstDataQueueSize
-{
- guint visible;
- guint bytes;
- guint64 time;
-};
-
-/**
- * GstDataQueueCheckFullFunction: (skip)
- * @queue: a #GstDataQueue.
- * @visible: The number of visible items currently in the queue.
- * @bytes: The amount of bytes currently in the queue.
- * @time: The accumulated duration of the items currently in the queue.
- * @checkdata: The #gpointer registered when the #GstDataQueue was created.
- *
- * The prototype of the function used to inform the queue that it should be
- * considered as full.
- *
- * Returns: %TRUE if the queue should be considered full.
- */
-typedef gboolean (*GstDataQueueCheckFullFunction) (GstDataQueue * queue,
- guint visible, guint bytes, guint64 time, gpointer checkdata);
-
-typedef void (*GstDataQueueFullCallback) (GstDataQueue * queue, gpointer checkdata);
-typedef void (*GstDataQueueEmptyCallback) (GstDataQueue * queue, gpointer checkdata);
-
-/**
- * GstDataQueue:
- * @object: the parent structure
- *
- * Opaque #GstDataQueue structure.
- */
-struct _GstDataQueue
-{
- GObject object;
-
- /*< private >*/
- GstDataQueuePrivate *priv;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstDataQueueClass:
- */
-struct _GstDataQueueClass
-{
- GObjectClass parent_class;
-
- /* signals */
- void (*empty) (GstDataQueue * queue);
- void (*full) (GstDataQueue * queue);
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_BASE_API
-GType gst_data_queue_get_type (void);
-
-GST_BASE_API
-GstDataQueue * gst_data_queue_new (GstDataQueueCheckFullFunction checkfull,
- GstDataQueueFullCallback fullcallback,
- GstDataQueueEmptyCallback emptycallback,
- gpointer checkdata) G_GNUC_MALLOC;
-GST_BASE_API
-gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item);
-
-GST_BASE_API
-gboolean gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item);
-
-GST_BASE_API
-gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item);
-
-GST_BASE_API
-gboolean gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item);
-
-GST_BASE_API
-void gst_data_queue_flush (GstDataQueue * queue);
-
-GST_BASE_API
-void gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing);
-
-GST_BASE_API
-gboolean gst_data_queue_drop_head (GstDataQueue * queue, GType type);
-
-GST_BASE_API
-gboolean gst_data_queue_is_full (GstDataQueue * queue);
-
-GST_BASE_API
-gboolean gst_data_queue_is_empty (GstDataQueue * queue);
-
-GST_BASE_API
-void gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize *level);
-
-GST_BASE_API
-void gst_data_queue_limits_changed (GstDataQueue * queue);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDataQueue, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_DATA_QUEUE_H__ */
diff --git a/libs/gst/base/gstflowcombiner.c b/libs/gst/base/gstflowcombiner.c
deleted file mode 100644
index d353eae4aa..0000000000
--- a/libs/gst/base/gstflowcombiner.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2014 Samsung Electronics. All rights reserved.
- * Author: Thiago Santos <ts.santos@sisa.samsung.com>
- *
- * gstflowcombiner.c: utility to combine multiple flow returns into a single one
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstflowcombiner
- * @title: GstFlowCombiner
- * @short_description: Utility to combine multiple flow returns into one
- *
- * Utility struct to help handling #GstFlowReturn combination. Useful for
- * #GstElement<!-- -->s that have multiple source pads and need to combine
- * the different #GstFlowReturn for those pads.
- *
- * #GstFlowCombiner works by using the last #GstFlowReturn for all #GstPad
- * it has in its list and computes the combined return value and provides
- * it to the caller.
- *
- * To add a new pad to the #GstFlowCombiner use gst_flow_combiner_add_pad().
- * The new #GstPad is stored with a default value of %GST_FLOW_OK.
- *
- * In case you want a #GstPad to be removed, use gst_flow_combiner_remove_pad().
- *
- * Please be aware that this struct isn't thread safe as its designed to be
- * used by demuxers, those usually will have a single thread operating it.
- *
- * These functions will take refs on the passed #GstPad<!-- -->s.
- *
- * Aside from reducing the user's code size, the main advantage of using this
- * helper struct is to follow the standard rules for #GstFlowReturn combination.
- * These rules are:
- *
- * * %GST_FLOW_EOS: only if all returns are EOS too
- * * %GST_FLOW_NOT_LINKED: only if all returns are NOT_LINKED too
- * * %GST_FLOW_ERROR or below: if at least one returns an error return
- * * %GST_FLOW_NOT_NEGOTIATED: if at least one returns a not-negotiated return
- * * %GST_FLOW_FLUSHING: if at least one returns flushing
- * * %GST_FLOW_OK: otherwise
- *
- * %GST_FLOW_ERROR or below, GST_FLOW_NOT_NEGOTIATED and GST_FLOW_FLUSHING are
- * returned immediately from the gst_flow_combiner_update_flow() function.
- *
- * Since: 1.4
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include "gstflowcombiner.h"
-
-struct _GstFlowCombiner
-{
- GQueue pads;
-
- GstFlowReturn last_ret;
- gint ref_count;
-};
-
-GST_DEBUG_CATEGORY_STATIC (flowcombiner_dbg);
-#define GST_CAT_DEFAULT flowcombiner_dbg
-
-G_DEFINE_BOXED_TYPE_WITH_CODE (GstFlowCombiner, gst_flow_combiner,
- (GBoxedCopyFunc) gst_flow_combiner_ref,
- (GBoxedFreeFunc) gst_flow_combiner_unref,
- GST_DEBUG_CATEGORY_INIT (flowcombiner_dbg, "flowcombiner", 0,
- "Flow Combiner"));
-
-/**
- * gst_flow_combiner_new:
- *
- * Creates a new #GstFlowCombiner, use gst_flow_combiner_free() to free it.
- *
- * Returns: A new #GstFlowCombiner
- * Since: 1.4
- */
-GstFlowCombiner *
-gst_flow_combiner_new (void)
-{
- GstFlowCombiner *combiner = g_slice_new (GstFlowCombiner);
-
- g_queue_init (&combiner->pads);
- combiner->last_ret = GST_FLOW_OK;
- g_atomic_int_set (&combiner->ref_count, 1);
-
- /* Make sure debug category is initialised */
- gst_flow_combiner_get_type ();
-
- return combiner;
-}
-
-/**
- * gst_flow_combiner_free:
- * @combiner: the #GstFlowCombiner to free
- *
- * Frees a #GstFlowCombiner struct and all its internal data.
- *
- * Since: 1.4
- */
-void
-gst_flow_combiner_free (GstFlowCombiner * combiner)
-{
- gst_flow_combiner_unref (combiner);
-}
-
-/**
- * gst_flow_combiner_ref:
- * @combiner: the #GstFlowCombiner to add a reference to.
- *
- * Increments the reference count on the #GstFlowCombiner.
- *
- * Returns: the #GstFlowCombiner.
- *
- * Since: 1.12.1
- */
-GstFlowCombiner *
-gst_flow_combiner_ref (GstFlowCombiner * combiner)
-{
- g_return_val_if_fail (combiner != NULL, NULL);
-
- g_atomic_int_inc (&combiner->ref_count);
-
- return combiner;
-}
-
-/**
- * gst_flow_combiner_unref:
- * @combiner: the #GstFlowCombiner to unreference.
- *
- * Decrements the reference count on the #GstFlowCombiner.
- *
- * Since: 1.12.1
- */
-void
-gst_flow_combiner_unref (GstFlowCombiner * combiner)
-{
- g_return_if_fail (combiner != NULL);
- g_return_if_fail (combiner->ref_count > 0);
-
- if (g_atomic_int_dec_and_test (&combiner->ref_count)) {
- GstPad *pad;
-
- while ((pad = g_queue_pop_head (&combiner->pads)))
- gst_object_unref (pad);
-
- g_slice_free (GstFlowCombiner, combiner);
- }
-}
-
-/**
- * gst_flow_combiner_clear:
- * @combiner: the #GstFlowCombiner to clear
- *
- * Removes all pads from a #GstFlowCombiner and resets it to its initial state.
- *
- * Since: 1.6
- */
-void
-gst_flow_combiner_clear (GstFlowCombiner * combiner)
-{
- GstPad *pad;
-
- g_return_if_fail (combiner != NULL);
-
- GST_DEBUG ("%p clearing", combiner);
-
- while ((pad = g_queue_pop_head (&combiner->pads)))
- gst_object_unref (pad);
- combiner->last_ret = GST_FLOW_OK;
-}
-
-/**
- * gst_flow_combiner_reset:
- * @combiner: the #GstFlowCombiner to clear
- *
- * Reset flow combiner and all pads to their initial state without removing pads.
- *
- * Since: 1.6
- */
-void
-gst_flow_combiner_reset (GstFlowCombiner * combiner)
-{
- GList *iter;
-
- g_return_if_fail (combiner != NULL);
-
- GST_DEBUG ("%p reset flow returns", combiner);
-
- for (iter = combiner->pads.head; iter; iter = iter->next) {
- GST_PAD_LAST_FLOW_RETURN (iter->data) = GST_FLOW_OK;
- }
-
- combiner->last_ret = GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_flow_combiner_get_flow (GstFlowCombiner * combiner)
-{
- GstFlowReturn cret = GST_FLOW_OK;
- gboolean all_eos = TRUE;
- gboolean all_notlinked = TRUE;
- GList *iter;
-
- GST_DEBUG ("%p Combining flow returns", combiner);
-
- for (iter = combiner->pads.head; iter; iter = iter->next) {
- GstFlowReturn fret = GST_PAD_LAST_FLOW_RETURN (iter->data);
-
- GST_TRACE ("%p pad %" GST_PTR_FORMAT " has flow return of %s (%d)",
- combiner, iter->data, gst_flow_get_name (fret), fret);
-
- if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) {
- GST_DEBUG ("%p Error flow return found, returning", combiner);
- cret = fret;
- goto done;
- }
-
- if (fret != GST_FLOW_NOT_LINKED) {
- all_notlinked = FALSE;
- if (fret != GST_FLOW_EOS)
- all_eos = FALSE;
- }
- }
- if (all_notlinked)
- cret = GST_FLOW_NOT_LINKED;
- else if (all_eos)
- cret = GST_FLOW_EOS;
-
-done:
- GST_DEBUG ("%p Combined flow return: %s (%d)", combiner,
- gst_flow_get_name (cret), cret);
- return cret;
-}
-
-/**
- * gst_flow_combiner_update_flow:
- * @combiner: the #GstFlowCombiner
- * @fret: the latest #GstFlowReturn received for a pad in this #GstFlowCombiner
- *
- * Computes the combined flow return for the pads in it.
- *
- * The #GstFlowReturn parameter should be the last flow return update for a pad
- * in this #GstFlowCombiner. It will use this value to be able to shortcut some
- * combinations and avoid looking over all pads again. e.g. The last combined
- * return is the same as the latest obtained #GstFlowReturn.
- *
- * Returns: The combined #GstFlowReturn
- * Since: 1.4
- */
-GstFlowReturn
-gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret)
-{
- GstFlowReturn ret;
-
- g_return_val_if_fail (combiner != NULL, GST_FLOW_ERROR);
-
- GST_DEBUG ("%p updating combiner with flow %s (%d)", combiner,
- gst_flow_get_name (fret), fret);
-
- if (combiner->last_ret == fret) {
- return fret;
- }
-
- if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING
- || !combiner->pads.head) {
- ret = fret;
- } else {
- ret = gst_flow_combiner_get_flow (combiner);
- }
- combiner->last_ret = ret;
- return ret;
-}
-
-/**
- * gst_flow_combiner_update_pad_flow:
- * @combiner: the #GstFlowCombiner
- * @pad: the #GstPad whose #GstFlowReturn to update
- * @fret: the latest #GstFlowReturn received for a pad in this #GstFlowCombiner
- *
- * Sets the provided pad's last flow return to provided value and computes
- * the combined flow return for the pads in it.
- *
- * The #GstFlowReturn parameter should be the last flow return update for a pad
- * in this #GstFlowCombiner. It will use this value to be able to shortcut some
- * combinations and avoid looking over all pads again. e.g. The last combined
- * return is the same as the latest obtained #GstFlowReturn.
- *
- * Returns: The combined #GstFlowReturn
- * Since: 1.6
- */
-GstFlowReturn
-gst_flow_combiner_update_pad_flow (GstFlowCombiner * combiner, GstPad * pad,
- GstFlowReturn fret)
-{
- g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
-
- GST_PAD_LAST_FLOW_RETURN (pad) = fret;
-
- return gst_flow_combiner_update_flow (combiner, fret);
-}
-
-/**
- * gst_flow_combiner_add_pad:
- * @combiner: the #GstFlowCombiner
- * @pad: (transfer none): the #GstPad that is being added
- *
- * Adds a new #GstPad to the #GstFlowCombiner.
- *
- * Since: 1.4
- */
-void
-gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad)
-{
- g_return_if_fail (combiner != NULL);
- g_return_if_fail (pad != NULL);
-
- g_queue_push_head (&combiner->pads, gst_object_ref (pad));
-}
-
-/**
- * gst_flow_combiner_remove_pad:
- * @combiner: the #GstFlowCombiner
- * @pad: (transfer none): the #GstPad to remove
- *
- * Removes a #GstPad from the #GstFlowCombiner.
- *
- * Since: 1.4
- */
-void
-gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad)
-{
- g_return_if_fail (combiner != NULL);
- g_return_if_fail (pad != NULL);
-
- if (g_queue_remove (&combiner->pads, pad))
- gst_object_unref (pad);
-}
diff --git a/libs/gst/base/gstflowcombiner.h b/libs/gst/base/gstflowcombiner.h
deleted file mode 100644
index fa905a93fc..0000000000
--- a/libs/gst/base/gstflowcombiner.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2014 Samsung Electronics. All rights reserved.
- * Author: Thiago Santos <ts.santos@sisa.samsung.com>
- *
- * gstflowcombiner.h: utility to combine multiple flow returns into a single one
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_FLOW_COMBINER_H__
-#define __GST_FLOW_COMBINER_H__
-
-#include <glib.h>
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_FLOW_COMBINER gst_flow_combiner_get_type()
-
-/**
- * GstFlowCombiner:
- *
- * Opaque helper structure to aggregate flow returns.
- *
- * Since: 1.4
- */
-typedef struct _GstFlowCombiner GstFlowCombiner;
-
-GST_BASE_API
-GstFlowCombiner * gst_flow_combiner_new (void);
-
-GST_BASE_API
-GstFlowCombiner * gst_flow_combiner_ref (GstFlowCombiner * combiner);
-
-GST_BASE_API
-void gst_flow_combiner_unref (GstFlowCombiner * combiner);
-
-GST_BASE_API
-void gst_flow_combiner_free (GstFlowCombiner * combiner);
-
-GST_BASE_API
-GstFlowReturn gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret);
-
-GST_BASE_API
-GstFlowReturn gst_flow_combiner_update_pad_flow (GstFlowCombiner * combiner, GstPad * pad,
- GstFlowReturn fret);
-GST_BASE_API
-void gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad);
-
-GST_BASE_API
-void gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad);
-
-GST_BASE_API
-void gst_flow_combiner_clear (GstFlowCombiner * combiner);
-
-GST_BASE_API
-void gst_flow_combiner_reset (GstFlowCombiner * combiner);
-
-GST_BASE_API
-GType gst_flow_combiner_get_type (void);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstFlowCombiner, gst_flow_combiner_free)
-
-G_END_DECLS
-
-#endif /* __GST_FLOW_COMBINER_H__ */
diff --git a/libs/gst/base/gstindex.c b/libs/gst/base/gstindex.c
deleted file mode 100644
index 964508e0ac..0000000000
--- a/libs/gst/base/gstindex.c
+++ /dev/null
@@ -1,1003 +0,0 @@
-/* GStreamer
- * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/)
- * Written by Erik Walthinsen <omega@ridgerun.com>
- *
- * gstindex.c: Index for mappings and other data
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstindex
- * @title: GstIndexEntry
- * @short_description: Generate indexes on objects
- * @see_also: #GstIndexFactory
- *
- * #GstIndex is used to generate a stream index of one or more elements
- * in a pipeline.
- *
- * Elements will overload the set_index and get_index virtual methods in
- * #GstElement. When streaming data, the element will add index entries if it
- * has an index set.
- *
- * Each element that adds to the index will do that using a writer_id. The
- * writer_id is obtained from gst_index_get_writer_id().
- *
- * The application that wants to index the stream will create a new index object
- * using gst_index_new() or gst_index_factory_make(). The index is assigned to a
- * specific element, a bin or the whole pipeline. This will cause indexable
- * elements to add entries to the index while playing.
- */
-
-/* FIXME: complete gobject annotations */
-/* FIXME-0.11: cleanup API
- * - no one seems to use GstIndexGroup, GstIndexCertainty
- *
- * - the API for application to use the index is mostly missing
- * - apps need to get a list of writers
- * - apps need to be able to iterate over each writers index entry collection
- * - gst_index_get_assoc_entry() should pass ownership
- * - the GstIndexEntry structure is large and contains repetitive information
- * - we want to allow Indexers to implement a saner storage and create
- * GstIndexEntries on demand (the app has to free them), might even make
- * sense to ask the app to provide a ptr and fill it.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include "gst/glib-compat-private.h"
-
-/* Index signals and args */
-enum
-{
- ENTRY_ADDED,
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_RESOLVER
- /* FILL ME */
-};
-
-#if 0
-GST_DEBUG_CATEGORY_STATIC (index_debug);
-#define GST_CAT_DEFAULT index_debug
-#endif
-
-static void gst_index_finalize (GObject * object);
-
-static void gst_index_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_index_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static GstIndexGroup *gst_index_group_new (guint groupnum);
-static void gst_index_group_free (GstIndexGroup * group);
-
-static gboolean gst_index_path_resolver (GstIndex * index, GstObject * writer,
- gchar ** writer_string, gpointer data);
-static gboolean gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
- gchar ** writer_string, gpointer data);
-static void gst_index_add_entry (GstIndex * index, GstIndexEntry * entry);
-
-static guint gst_index_signals[LAST_SIGNAL] = { 0 };
-
-typedef struct
-{
- GstIndexResolverMethod method;
- GstIndexResolver resolver;
- gpointer user_data;
-}
-ResolverEntry;
-
-static const ResolverEntry resolvers[] = {
- {GST_INDEX_RESOLVER_CUSTOM, NULL, NULL},
- {GST_INDEX_RESOLVER_GTYPE, gst_index_gtype_resolver, NULL},
- {GST_INDEX_RESOLVER_PATH, gst_index_path_resolver, NULL},
-};
-
-#define GST_TYPE_INDEX_RESOLVER (gst_index_resolver_get_type())
-static GType
-gst_index_resolver_get_type (void)
-{
- static GType index_resolver_type = 0;
- static const GEnumValue index_resolver[] = {
- {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM", "custom"},
- {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE", "gtype"},
- {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH", "path"},
- {0, NULL, NULL},
- };
-
- if (!index_resolver_type) {
- index_resolver_type =
- g_enum_register_static ("GstIndexResolver", index_resolver);
- }
- return index_resolver_type;
-}
-
-G_DEFINE_BOXED_TYPE (GstIndexEntry, gst_index_entry,
- (GBoxedCopyFunc) gst_index_entry_copy,
- (GBoxedFreeFunc) gst_index_entry_free);
-
-#if 0
-#define _do_init \
-{ \
- GST_DEBUG_CATEGORY_INIT (index_debug, "GST_INDEX", GST_DEBUG_BOLD, \
- "Generic indexing support"); \
-}
-#endif
-
-G_DEFINE_TYPE (GstIndex, gst_index, GST_TYPE_OBJECT);
-
-static void
-gst_index_class_init (GstIndexClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- /**
- * GstIndex::entry-added
- * @gstindex: the object which received the signal.
- * @arg1: The entry added to the index.
- *
- * Is emitted when a new entry is added to the index.
- */
- gst_index_signals[ENTRY_ADDED] =
- g_signal_new ("entry-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL,
- NULL, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY);
-
- gobject_class->set_property = gst_index_set_property;
- gobject_class->get_property = gst_index_get_property;
- gobject_class->finalize = gst_index_finalize;
-
- g_object_class_install_property (gobject_class, ARG_RESOLVER,
- g_param_spec_enum ("resolver", "Resolver",
- "Select a predefined object to string mapper",
- GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gst_index_init (GstIndex * index)
-{
- index->curgroup = gst_index_group_new (0);
- index->maxgroup = 0;
- index->groups = g_list_prepend (NULL, index->curgroup);
-
- index->writers = g_hash_table_new (NULL, NULL);
- index->last_id = 0;
-
- index->method = GST_INDEX_RESOLVER_PATH;
- index->resolver = resolvers[index->method].resolver;
- index->resolver_user_data = resolvers[index->method].user_data;
-
- GST_OBJECT_FLAG_SET (index, GST_INDEX_WRITABLE);
- GST_OBJECT_FLAG_SET (index, GST_INDEX_READABLE);
-
- GST_DEBUG ("created new index");
-}
-
-static void
-gst_index_free_writer (gpointer key, gpointer value, gpointer user_data)
-{
- GstIndexEntry *entry = (GstIndexEntry *) value;
-
- if (entry) {
- gst_index_entry_free (entry);
- }
-}
-
-static void
-gst_index_finalize (GObject * object)
-{
- GstIndex *index = GST_INDEX (object);
-
- if (index->groups) {
- g_list_foreach (index->groups, (GFunc) gst_index_group_free, NULL);
- g_list_free (index->groups);
- index->groups = NULL;
- }
-
- if (index->writers) {
- g_hash_table_foreach (index->writers, gst_index_free_writer, NULL);
- g_hash_table_destroy (index->writers);
- index->writers = NULL;
- }
-
- if (index->filter_user_data && index->filter_user_data_destroy)
- index->filter_user_data_destroy (index->filter_user_data);
-
- if (index->resolver_user_data && index->resolver_user_data_destroy)
- index->resolver_user_data_destroy (index->resolver_user_data);
-
- G_OBJECT_CLASS (gst_index_parent_class)->finalize (object);
-}
-
-static void
-gst_index_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstIndex *index;
-
- index = GST_INDEX (object);
-
- switch (prop_id) {
- case ARG_RESOLVER:
- index->method = (GstIndexResolverMethod) g_value_get_enum (value);
- index->resolver = resolvers[index->method].resolver;
- index->resolver_user_data = resolvers[index->method].user_data;
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_index_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstIndex *index;
-
- index = GST_INDEX (object);
-
- switch (prop_id) {
- case ARG_RESOLVER:
- g_value_set_enum (value, index->method);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static GstIndexGroup *
-gst_index_group_new (guint groupnum)
-{
- GstIndexGroup *indexgroup = g_slice_new (GstIndexGroup);
-
- indexgroup->groupnum = groupnum;
- indexgroup->entries = NULL;
- indexgroup->certainty = GST_INDEX_UNKNOWN;
- indexgroup->peergroup = -1;
-
- GST_DEBUG ("created new index group %d", groupnum);
-
- return indexgroup;
-}
-
-static void
-gst_index_group_free (GstIndexGroup * group)
-{
- g_slice_free (GstIndexGroup, group);
-}
-
-/* do not resurrect this, add a derived dummy index class instead */
-#if 0
-/**
- * gst_index_new:
- *
- * Create a new dummy index object. Use gst_element_set_index() to assign that
- * to an element or pipeline. This index is not storing anything, but will
- * still emit e.g. the #GstIndex::entry-added signal.
- *
- * Returns: (transfer full): a new index object
- */
-GstIndex *
-gst_index_new (void)
-{
- GstIndex *index;
-
- index = g_object_new (gst_index_get_type (), NULL);
-
- return index;
-}
-
-/**
- * gst_index_commit:
- * @index: the index to commit
- * @id: the writer that committed the index
- *
- * Tell the index that the writer with the given id is done
- * with this index and is not going to write any more entries
- * to it.
- */
-void
-gst_index_commit (GstIndex * index, gint id)
-{
- GstIndexClass *iclass;
-
- iclass = GST_INDEX_GET_CLASS (index);
-
- if (iclass->commit)
- iclass->commit (index, id);
-}
-
-/**
- * gst_index_get_group:
- * @index: the index to get the current group from
- *
- * Get the id of the current group.
- *
- * Returns: the id of the current group.
- */
-gint
-gst_index_get_group (GstIndex * index)
-{
- return index->curgroup->groupnum;
-}
-
-/**
- * gst_index_new_group:
- * @index: the index to create the new group in
- *
- * Create a new group for the given index. It will be
- * set as the current group.
- *
- * Returns: the id of the newly created group.
- */
-gint
-gst_index_new_group (GstIndex * index)
-{
- index->curgroup = gst_index_group_new (++index->maxgroup);
- index->groups = g_list_append (index->groups, index->curgroup);
- GST_DEBUG ("created new group %d in index", index->maxgroup);
- return index->maxgroup;
-}
-
-/**
- * gst_index_set_group:
- * @index: the index to set the new group in
- * @groupnum: the groupnumber to set
- *
- * Set the current groupnumber to the given argument.
- *
- * Returns: %TRUE if the operation succeeded, %FALSE if the group
- * did not exist.
- */
-gboolean
-gst_index_set_group (GstIndex * index, gint groupnum)
-{
- GList *list;
- GstIndexGroup *indexgroup;
-
- /* first check for null change */
- if (groupnum == index->curgroup->groupnum)
- return TRUE;
-
- /* else search for the proper group */
- list = index->groups;
- while (list) {
- indexgroup = (GstIndexGroup *) (list->data);
- list = g_list_next (list);
- if (indexgroup->groupnum == groupnum) {
- index->curgroup = indexgroup;
- GST_DEBUG ("switched to index group %d", indexgroup->groupnum);
- return TRUE;
- }
- }
-
- /* couldn't find the group in question */
- GST_DEBUG ("couldn't find index group %d", groupnum);
- return FALSE;
-}
-#endif
-
-#if 0
-/**
- * gst_index_set_certainty:
- * @index: the index to set the certainty on
- * @certainty: the certainty to set
- *
- * Set the certainty of the given index.
- */
-void
-gst_index_set_certainty (GstIndex * index, GstIndexCertainty certainty)
-{
- index->curgroup->certainty = certainty;
-}
-
-/**
- * gst_index_get_certainty:
- * @index: the index to get the certainty of
- *
- * Get the certainty of the given index.
- *
- * Returns: the certainty of the index.
- */
-GstIndexCertainty
-gst_index_get_certainty (GstIndex * index)
-{
- return index->curgroup->certainty;
-}
-#endif
-
-#if 0
-/**
- * gst_index_set_filter:
- * @index: the index to register the filter on
- * @filter: the filter to register
- * @user_data: data passed to the filter function
- *
- * Lets the app register a custom filter function so that
- * it can select what entries should be stored in the index.
- */
-void
-gst_index_set_filter (GstIndex * index,
- GstIndexFilter filter, gpointer user_data)
-{
- g_return_if_fail (GST_IS_INDEX (index));
-
- gst_index_set_filter_full (index, filter, user_data, NULL);
-}
-
-/**
- * gst_index_set_filter_full:
- * @index: the index to register the filter on
- * @filter: the filter to register
- * @user_data: data passed to the filter function
- * @user_data_destroy: function to call when @user_data is unset
- *
- * Lets the app register a custom filter function so that
- * it can select what entries should be stored in the index.
- */
-void
-gst_index_set_filter_full (GstIndex * index,
- GstIndexFilter filter, gpointer user_data, GDestroyNotify user_data_destroy)
-{
- g_return_if_fail (GST_IS_INDEX (index));
-
- if (index->filter_user_data && index->filter_user_data_destroy)
- index->filter_user_data_destroy (index->filter_user_data);
-
- index->filter = filter;
- index->filter_user_data = user_data;
- index->filter_user_data_destroy = user_data_destroy;
-}
-
-/**
- * gst_index_set_resolver:
- * @index: the index to register the resolver on
- * @resolver: the resolver to register
- * @user_data: data passed to the resolver function
- *
- * Lets the app register a custom function to map index
- * ids to writer descriptions.
- */
-void
-gst_index_set_resolver (GstIndex * index,
- GstIndexResolver resolver, gpointer user_data)
-{
- gst_index_set_resolver_full (index, resolver, user_data, NULL);
-}
-
-/**
- * gst_index_set_resolver_full:
- * @index: the index to register the resolver on
- * @resolver: the resolver to register
- * @user_data: data passed to the resolver function
- * @user_data_destroy: destroy function for @user_data
- *
- * Lets the app register a custom function to map index
- * ids to writer descriptions.
- */
-void
-gst_index_set_resolver_full (GstIndex * index, GstIndexResolver resolver,
- gpointer user_data, GDestroyNotify user_data_destroy)
-{
- g_return_if_fail (GST_IS_INDEX (index));
-
- if (index->resolver_user_data && index->resolver_user_data_destroy)
- index->resolver_user_data_destroy (index->resolver_user_data);
-
- index->resolver = resolver;
- index->resolver_user_data = user_data;
- index->resolver_user_data_destroy = user_data_destroy;
- index->method = GST_INDEX_RESOLVER_CUSTOM;
-}
-#endif
-
-/**
- * gst_index_entry_copy:
- * @entry: the entry to copy
- *
- * Copies an entry and returns the result.
- *
- * Free-function: gst_index_entry_free
- *
- * Returns: (transfer full): a newly allocated #GstIndexEntry.
- */
-GstIndexEntry *
-gst_index_entry_copy (GstIndexEntry * entry)
-{
- GstIndexEntry *new_entry = g_slice_new (GstIndexEntry);
-
- memcpy (new_entry, entry, sizeof (GstIndexEntry));
- return new_entry;
-}
-
-/**
- * gst_index_entry_free:
- * @entry: (transfer full): the entry to free
- *
- * Free the memory used by the given entry.
- */
-void
-gst_index_entry_free (GstIndexEntry * entry)
-{
- switch (entry->type) {
- case GST_INDEX_ENTRY_ID:
- if (entry->data.id.description) {
- g_free (entry->data.id.description);
- entry->data.id.description = NULL;
- }
- break;
- case GST_INDEX_ENTRY_ASSOCIATION:
- if (entry->data.assoc.assocs) {
- g_free (entry->data.assoc.assocs);
- entry->data.assoc.assocs = NULL;
- }
- break;
- case GST_INDEX_ENTRY_OBJECT:
- break;
- case GST_INDEX_ENTRY_FORMAT:
- break;
- }
-
- g_slice_free (GstIndexEntry, entry);
-}
-
-#if 0
-/**
- * gst_index_add_format:
- * @index: the index to add the entry to
- * @id: the id of the index writer
- * @format: the format to add to the index
- *
- * Adds a format entry into the index. This function is
- * used to map dynamic #GstFormat ids to their original
- * format key.
- *
- * Free-function: gst_index_entry_free
- *
- * Returns: (transfer full): a pointer to the newly added entry in the index.
- */
-GstIndexEntry *
-gst_index_add_format (GstIndex * index, gint id, GstFormat format)
-{
- GstIndexEntry *entry;
- const GstFormatDefinition *def;
-
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
- g_return_val_if_fail (format != 0, NULL);
-
- if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
- return NULL;
-
- entry = g_slice_new (GstIndexEntry);
- entry->type = GST_INDEX_ENTRY_FORMAT;
- entry->id = id;
- entry->data.format.format = format;
-
- def = gst_format_get_details (format);
- entry->data.format.key = def->nick;
-
- gst_index_add_entry (index, entry);
-
- return entry;
-}
-#endif
-
-/**
- * gst_index_add_id:
- * @index: the index to add the entry to
- * @id: the id of the index writer
- * @description: the description of the index writer
- *
- * Add an id entry into the index.
- *
- * Returns: a pointer to the newly added entry in the index.
- */
-GstIndexEntry *
-gst_index_add_id (GstIndex * index, gint id, gchar * description)
-{
- GstIndexEntry *entry;
-
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
- g_return_val_if_fail (description != NULL, NULL);
-
- if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
- return NULL;
-
- entry = g_slice_new (GstIndexEntry);
- entry->type = GST_INDEX_ENTRY_ID;
- entry->id = id;
- entry->data.id.description = description;
-
- gst_index_add_entry (index, entry);
-
- return entry;
-}
-
-static gboolean
-gst_index_path_resolver (GstIndex * index, GstObject * writer,
- gchar ** writer_string, gpointer data)
-{
- *writer_string = gst_object_get_path_string (writer);
-
- return TRUE;
-}
-
-static gboolean
-gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
- gchar ** writer_string, gpointer data)
-{
- g_return_val_if_fail (writer != NULL, FALSE);
-
- if (GST_IS_PAD (writer)) {
- GstObject *element = gst_object_get_parent (GST_OBJECT (writer));
- gchar *name;
-
- name = gst_object_get_name (writer);
- if (element) {
- *writer_string = g_strdup_printf ("%s.%s",
- G_OBJECT_TYPE_NAME (element), name);
- gst_object_unref (element);
- } else {
- *writer_string = name;
- name = NULL;
- }
-
- g_free (name);
-
- } else {
- *writer_string = g_strdup (G_OBJECT_TYPE_NAME (writer));
- }
-
- return TRUE;
-}
-
-/**
- * gst_index_get_writer_id:
- * @index: the index to get a unique write id for
- * @writer: the #GstObject to allocate an id for
- * @id: a pointer to a gint to hold the id
- *
- * Before entries can be added to the index, a writer
- * should obtain a unique id. The methods to add new entries
- * to the index require this id as an argument.
- *
- * The application can implement a custom function to map the writer object
- * to a string. That string will be used to register or look up an id
- * in the index.
- *
- * > The caller must not hold @writer's GST_OBJECT_LOCK(), as the default
- * > resolver may call functions that take the object lock as well, and
- * > the lock is not recursive.
- *
- * Returns: %TRUE if the writer would be mapped to an id.
- */
-gboolean
-gst_index_get_writer_id (GstIndex * index, GstObject * writer, gint * id)
-{
- gchar *writer_string = NULL;
- GstIndexEntry *entry;
- GstIndexClass *iclass;
- gboolean success = FALSE;
-
- g_return_val_if_fail (GST_IS_INDEX (index), FALSE);
- g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE);
- g_return_val_if_fail (id, FALSE);
-
- *id = -1;
-
- /* first try to get a previously cached id */
- entry = g_hash_table_lookup (index->writers, writer);
- if (entry == NULL) {
-
- iclass = GST_INDEX_GET_CLASS (index);
-
- /* let the app make a string */
- if (index->resolver) {
- gboolean res;
-
- res =
- index->resolver (index, writer, &writer_string,
- index->resolver_user_data);
- if (!res)
- return FALSE;
- } else {
- g_warning ("no resolver found");
- return FALSE;
- }
-
- /* if the index has a resolver, make it map this string to an id */
- if (iclass->get_writer_id) {
- success = iclass->get_writer_id (index, id, writer_string);
- }
- /* if the index could not resolve, we allocate one ourselves */
- if (!success) {
- *id = ++index->last_id;
- }
-
- entry = gst_index_add_id (index, *id, writer_string);
- if (!entry) {
- /* index is probably not writable, make an entry anyway
- * to keep it in our cache */
- entry = g_slice_new (GstIndexEntry);
- entry->type = GST_INDEX_ENTRY_ID;
- entry->id = *id;
- entry->data.id.description = writer_string;
- }
- g_hash_table_insert (index->writers, writer, entry);
- } else {
- *id = entry->id;
- }
-
- return TRUE;
-}
-
-static void
-gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
-{
- GstIndexClass *iclass;
-
- iclass = GST_INDEX_GET_CLASS (index);
-
- if (iclass->add_entry) {
- iclass->add_entry (index, entry);
- }
-
- g_signal_emit (index, gst_index_signals[ENTRY_ADDED], 0, entry);
-}
-
-/**
- * gst_index_add_associationv:
- * @index: the index to add the entry to
- * @id: the id of the index writer
- * @flags: optional flags for this entry
- * @n: number of associations
- * @list: (array length=n): list of associations
- *
- * Associate given format/value pairs with each other.
- *
- * Returns: a pointer to the newly added entry in the index.
- */
-GstIndexEntry *
-gst_index_add_associationv (GstIndex * index, gint id,
- GstIndexAssociationFlags flags, gint n, const GstIndexAssociation * list)
-{
- GstIndexEntry *entry;
-
- g_return_val_if_fail (n > 0, NULL);
- g_return_val_if_fail (list != NULL, NULL);
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
-
- if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
- return NULL;
-
- entry = g_slice_new (GstIndexEntry);
-
- entry->type = GST_INDEX_ENTRY_ASSOCIATION;
- entry->id = id;
- entry->data.assoc.flags = flags;
- entry->data.assoc.assocs = g_memdup2 (list, sizeof (GstIndexAssociation) * n);
- entry->data.assoc.nassocs = n;
-
- gst_index_add_entry (index, entry);
-
- return entry;
-}
-
-#if 0
-/**
- * gst_index_add_association:
- * @index: the index to add the entry to
- * @id: the id of the index writer
- * @flags: optional flags for this entry
- * @format: the format of the value
- * @value: the value
- * @...: other format/value pairs or 0 to end the list
- *
- * Associate given format/value pairs with each other.
- * Be sure to pass gint64 values to this functions varargs,
- * you might want to use a gint64 cast to be sure.
- *
- * Returns: a pointer to the newly added entry in the index.
- */
-GstIndexEntry *
-gst_index_add_association (GstIndex * index, gint id,
- GstIndexAssociationFlags flags, GstFormat format, gint64 value, ...)
-{
- va_list args;
- GstIndexEntry *entry;
- GstIndexAssociation *list;
- gint n_assocs = 0;
- GstFormat cur_format;
- GArray *array;
-
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
- g_return_val_if_fail (format != 0, NULL);
-
- if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
- return NULL;
-
- array = g_array_new (FALSE, FALSE, sizeof (GstIndexAssociation));
-
- {
- GstIndexAssociation a;
-
- a.format = format;
- a.value = value;
- n_assocs = 1;
- g_array_append_val (array, a);
- }
-
- va_start (args, value);
-
- while ((cur_format = va_arg (args, GstFormat))) {
- GstIndexAssociation a;
-
- a.format = cur_format;
- a.value = va_arg (args, gint64);
- n_assocs++;
- g_array_append_val (array, a);
- }
-
- va_end (args);
-
- list = (GstIndexAssociation *) g_array_free (array, FALSE);
-
- entry = gst_index_add_associationv (index, id, flags, n_assocs, list);
- g_free (list);
-
- return entry;
-}
-
-/**
- * gst_index_add_object:
- * @index: the index to add the object to
- * @id: the id of the index writer
- * @key: a key for the object
- * @type: the GType of the object
- * @object: a pointer to the object to add
- *
- * Add the given object to the index with the given key.
- *
- * This function is not yet implemented.
- *
- * Returns: a pointer to the newly added entry in the index.
- */
-GstIndexEntry *
-gst_index_add_object (GstIndex * index, gint id, gchar * key,
- GType type, gpointer object)
-{
- if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
- return NULL;
-
- return NULL;
-}
-#endif
-
-static gint
-gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
-{
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
-}
-
-/**
- * gst_index_get_assoc_entry:
- * @index: the index to search
- * @id: the id of the index writer
- * @method: The lookup method to use
- * @flags: Flags for the entry
- * @format: the format of the value
- * @value: the value to find
- *
- * Finds the given format/value in the index
- *
- * Returns: (nullable): the entry associated with the value or %NULL if the
- * value was not found.
- */
-GstIndexEntry *
-gst_index_get_assoc_entry (GstIndex * index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value)
-{
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
-
- if (id == -1)
- return NULL;
-
- return gst_index_get_assoc_entry_full (index, id, method, flags, format,
- value, gst_index_compare_func, NULL);
-}
-
-/**
- * gst_index_get_assoc_entry_full:
- * @index: the index to search
- * @id: the id of the index writer
- * @method: The lookup method to use
- * @flags: Flags for the entry
- * @format: the format of the value
- * @value: the value to find
- * @func: the function used to compare entries
- * @user_data: user data passed to the compare function
- *
- * Finds the given format/value in the index with the given
- * compare function and user_data.
- *
- * Returns: (nullable): the entry associated with the value or %NULL if the
- * value was not found.
- */
-GstIndexEntry *
-gst_index_get_assoc_entry_full (GstIndex * index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
-{
- GstIndexClass *iclass;
-
- g_return_val_if_fail (GST_IS_INDEX (index), NULL);
-
- if (id == -1)
- return NULL;
-
- iclass = GST_INDEX_GET_CLASS (index);
-
- if (iclass->get_assoc_entry)
- return iclass->get_assoc_entry (index, id, method, flags, format, value,
- func, user_data);
-
- return NULL;
-}
-
-/**
- * gst_index_entry_assoc_map:
- * @entry: the index to search
- * @format: the format of the value the find
- * @value: a pointer to store the value
- *
- * Gets alternative formats associated with the indexentry.
- *
- * Returns: %TRUE if there was a value associated with the given
- * format.
- */
-gboolean
-gst_index_entry_assoc_map (GstIndexEntry * entry,
- GstFormat format, gint64 * value)
-{
- gint i;
-
- g_return_val_if_fail (entry != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
-
- for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
- if (GST_INDEX_ASSOC_FORMAT (entry, i) == format) {
- *value = GST_INDEX_ASSOC_VALUE (entry, i);
- return TRUE;
- }
- }
- return FALSE;
-}
diff --git a/libs/gst/base/gstindex.h b/libs/gst/base/gstindex.h
deleted file mode 100644
index 476146574b..0000000000
--- a/libs/gst/base/gstindex.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wim.taymans@chello.be>
- *
- * gstindex.h: Header for GstIndex, base class to handle efficient
- * storage or caching of seeking information.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_INDEX_H__
-#define __GST_INDEX_H__
-
-#include <gst/gstobject.h>
-#include <gst/gstformat.h>
-#include <gst/gstpluginfeature.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_INDEX (gst_index_get_type ())
-#define GST_INDEX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INDEX, GstIndex))
-#define GST_IS_INDEX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INDEX))
-#define GST_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INDEX, GstIndexClass))
-#define GST_IS_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INDEX))
-#define GST_INDEX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_INDEX, GstIndexClass))
-
-#define GST_TYPE_INDEX_ENTRY (gst_index_entry_get_type())
-
-typedef struct _GstIndexEntry GstIndexEntry;
-typedef struct _GstIndexGroup GstIndexGroup;
-typedef struct _GstIndex GstIndex;
-typedef struct _GstIndexClass GstIndexClass;
-
-/**
- * GstIndexCertainty:
- * @GST_INDEX_UNKNOWN: accuracy is not known
- * @GST_INDEX_CERTAIN: accuracy is perfect
- * @GST_INDEX_FUZZY: accuracy is fuzzy
- *
- * The certainty of a group in the index.
- */
-typedef enum {
- GST_INDEX_UNKNOWN,
- GST_INDEX_CERTAIN,
- GST_INDEX_FUZZY
-} GstIndexCertainty;
-
-/**
- * GstIndexEntryType:
- * @GST_INDEX_ENTRY_ID: This entry is an id that maps an index id to its owner object
- * @GST_INDEX_ENTRY_ASSOCIATION: This entry is an association between formats
- * @GST_INDEX_ENTRY_OBJECT: An object
- * @GST_INDEX_ENTRY_FORMAT: A format definition
- *
- * The different types of entries in the index.
- */
-typedef enum {
- GST_INDEX_ENTRY_ID,
- GST_INDEX_ENTRY_ASSOCIATION,
- GST_INDEX_ENTRY_OBJECT,
- GST_INDEX_ENTRY_FORMAT
-} GstIndexEntryType;
-
-/**
- * GstIndexLookupMethod:
- * @GST_INDEX_LOOKUP_EXACT: There has to be an exact indexentry with the given format/value
- * @GST_INDEX_LOOKUP_BEFORE: The exact entry or the one before it
- * @GST_INDEX_LOOKUP_AFTER: The exact entry or the one after it
- *
- * Specify the method to find an index entry in the index.
- */
-typedef enum {
- GST_INDEX_LOOKUP_EXACT,
- GST_INDEX_LOOKUP_BEFORE,
- GST_INDEX_LOOKUP_AFTER
-} GstIndexLookupMethod;
-
-/**
- * GST_INDEX_NASSOCS:
- * @entry: The entry to query
- *
- * Get the number of associations in the entry.
- */
-#define GST_INDEX_NASSOCS(entry) ((entry)->data.assoc.nassocs)
-
-/**
- * GST_INDEX_ASSOC_FLAGS:
- * @entry: The entry to query
- *
- * Get the flags for this entry.
- */
-#define GST_INDEX_ASSOC_FLAGS(entry) ((entry)->data.assoc.flags)
-
-/**
- * GST_INDEX_ASSOC_FORMAT:
- * @entry: The entry to query
- * @i: The format index
- *
- * Get the i-th format of the entry.
- */
-#define GST_INDEX_ASSOC_FORMAT(entry,i) ((entry)->data.assoc.assocs[(i)].format)
-
-/**
- * GST_INDEX_ASSOC_VALUE:
- * @entry: The entry to query
- * @i: The value index
- *
- * Get the i-th value of the entry.
- */
-#define GST_INDEX_ASSOC_VALUE(entry,i) ((entry)->data.assoc.assocs[(i)].value)
-
-typedef struct _GstIndexAssociation GstIndexAssociation;
-
-/**
- * GstIndexAssociation:
- * @format: the format of the association
- * @value: the value of the association
- *
- * An association in an entry.
- */
-struct _GstIndexAssociation {
- GstFormat format;
- gint64 value;
-};
-
-/**
- * GstIndexAssociationFlags:
- * @GST_INDEX_ASSOCIATION_FLAG_NONE: no extra flags
- * @GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT: the entry marks a key unit, a key unit is one
- * that marks a place where one can randomly seek to.
- * @GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT: the entry marks a delta unit, a delta unit
- * is one that marks a place where one can relatively seek to.
- * @GST_INDEX_ASSOCIATION_FLAG_LAST: extra user defined flags should start here.
- *
- * Flags for an association entry.
- */
-typedef enum {
- GST_INDEX_ASSOCIATION_FLAG_NONE = 0,
- GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT = (1 << 0),
- GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT = (1 << 1),
-
- /* new flags should start here */
- GST_INDEX_ASSOCIATION_FLAG_LAST = (1 << 8)
-} GstIndexAssociationFlags;
-
-/**
- * GST_INDEX_FORMAT_FORMAT:
- * @entry: The entry to query
- *
- * Get the format of the format entry
- */
-#define GST_INDEX_FORMAT_FORMAT(entry) ((entry)->data.format.format)
-
-/**
- * GST_INDEX_FORMAT_KEY:
- * @entry: The entry to query
- *
- * Get the key of the format entry
- */
-#define GST_INDEX_FORMAT_KEY(entry) ((entry)->data.format.key)
-
-/**
- * GST_INDEX_ID_INVALID:
- *
- * Constant for an invalid index id
- */
-#define GST_INDEX_ID_INVALID (-1)
-
-/**
- * GST_INDEX_ID_DESCRIPTION:
- * @entry: The entry to query
- *
- * Get the description of the id entry
- */
-#define GST_INDEX_ID_DESCRIPTION(entry) ((entry)->data.id.description)
-
-/**
- * GstIndexEntry:
- *
- * The basic element of an index.
- */
-struct _GstIndexEntry {
- /*< private >*/
- GstIndexEntryType type;
- gint id;
-
- union {
- struct {
- gchar *description;
- } id;
- struct {
- gint nassocs;
- GstIndexAssociation
- *assocs;
- GstIndexAssociationFlags flags;
- } assoc;
- struct {
- gchar *key;
- GType type;
- gpointer object;
- } object;
- struct {
- GstFormat format;
- const gchar *key;
- } format;
- } data;
- // FIXME 2.0: add padding
-};
-
-/**
- * GstIndexGroup:
- *
- * A group of related entries in an index.
- */
-
-struct _GstIndexGroup {
- /*< private >*/
- /* unique ID of group in index */
- gint groupnum;
-
- /* list of entries */
- GList *entries;
-
- /* the certainty level of the group */
- GstIndexCertainty certainty;
-
- /* peer group that contains more certain entries */
- gint peergroup;
- // FIXME 2.0: add padding
-};
-
-/**
- * GstIndexFilter:
- * @index: The index being queried
- * @entry: The entry to be added.
- * @user_data: User data passed to the function.
- *
- * Function to filter out entries in the index.
- *
- * Returns: This function should return %TRUE if the entry is to be added
- * to the index, %FALSE otherwise.
- *
- */
-typedef gboolean (*GstIndexFilter) (GstIndex *index,
- GstIndexEntry *entry,
- gpointer user_data);
-/**
- * GstIndexResolverMethod:
- * @GST_INDEX_RESOLVER_CUSTOM: Use a custom resolver
- * @GST_INDEX_RESOLVER_GTYPE: Resolve based on the GType of the object
- * @GST_INDEX_RESOLVER_PATH: Resolve on the path in graph
- *
- * The method used to resolve index writers
- */
-typedef enum {
- GST_INDEX_RESOLVER_CUSTOM,
- GST_INDEX_RESOLVER_GTYPE,
- GST_INDEX_RESOLVER_PATH
-} GstIndexResolverMethod;
-
-/**
- * GstIndexResolver:
- * @index: the index being queried.
- * @writer: The object that wants to write
- * @writer_string: A description of the writer.
- * @user_data: user_data as registered
- *
- * Function to resolve ids to writer descriptions.
- *
- * Returns: %TRUE if an id could be assigned to the writer.
- */
-typedef gboolean (*GstIndexResolver) (GstIndex *index,
- GstObject *writer,
- gchar **writer_string,
- gpointer user_data);
-
-/**
- * GstIndexFlags:
- * @GST_INDEX_WRITABLE: The index is writable
- * @GST_INDEX_READABLE: The index is readable
- * @GST_INDEX_FLAG_LAST: First flag that can be used by subclasses
- *
- * Flags for this index
- */
-typedef enum {
- GST_INDEX_WRITABLE = (GST_OBJECT_FLAG_LAST << 0),
- GST_INDEX_READABLE = (GST_OBJECT_FLAG_LAST << 1),
-
- GST_INDEX_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8)
-} GstIndexFlags;
-
-/**
- * GST_INDEX_IS_READABLE:
- * @obj: The index to check
- *
- * Check if the index can be read from
- */
-#define GST_INDEX_IS_READABLE(obj) (GST_OBJECT_FLAG_IS_SET (obj, GST_INDEX_READABLE))
-
-/**
- * GST_INDEX_IS_WRITABLE:
- * @obj: The index to check
- *
- * Check if the index can be written to
- */
-#define GST_INDEX_IS_WRITABLE(obj) (GST_OBJECT_FLAG_IS_SET (obj, GST_INDEX_WRITABLE))
-
-/**
- * GstIndex:
- *
- * Opaque #GstIndex structure.
- */
-struct _GstIndex {
- GstObject object;
-
- /*< private >*/
- GList *groups;
- GstIndexGroup *curgroup;
- gint maxgroup;
-
- GstIndexResolverMethod method;
- GstIndexResolver resolver;
- gpointer resolver_user_data;
- GDestroyNotify resolver_user_data_destroy;
-
- GstIndexFilter filter;
- gpointer filter_user_data;
- GDestroyNotify filter_user_data_destroy;
-
- GHashTable *writers;
- gint last_id;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstIndexClass {
- GstObjectClass parent_class;
-
- /*< protected >*/
- gboolean (*get_writer_id) (GstIndex *index, gint *id, gchar *writer);
-
- void (*commit) (GstIndex *index, gint id);
-
- /* abstract methods */
- void (*add_entry) (GstIndex *index, GstIndexEntry *entry);
-
- GstIndexEntry* (*get_assoc_entry) (GstIndex *index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value,
- GCompareDataFunc func,
- gpointer user_data);
- /* signals */
- void (*entry_added) (GstIndex *index, GstIndexEntry *entry);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-static
-GType gst_index_get_type (void);
-
-#if 0
-GstIndex* gst_index_new (void);
-void gst_index_commit (GstIndex *index, gint id);
-
-gint gst_index_get_group (GstIndex *index);
-gint gst_index_new_group (GstIndex *index);
-gboolean gst_index_set_group (GstIndex *index, gint groupnum);
-
-void gst_index_set_certainty (GstIndex *index,
- GstIndexCertainty certainty);
-GstIndexCertainty gst_index_get_certainty (GstIndex *index);
-
-static
-void gst_index_set_filter (GstIndex *index,
- GstIndexFilter filter, gpointer user_data);
-static
-void gst_index_set_filter_full (GstIndex *index,
- GstIndexFilter filter, gpointer user_data,
- GDestroyNotify user_data_destroy);
-
-void gst_index_set_resolver (GstIndex *index,
- GstIndexResolver resolver, gpointer user_data);
-void gst_index_set_resolver_full (GstIndex *index, GstIndexResolver resolver,
- gpointer user_data,
- GDestroyNotify user_data_destroy);
-#endif
-
-static
-gboolean gst_index_get_writer_id (GstIndex *index, GstObject *writer, gint *id);
-
-#if 0
-GstIndexEntry* gst_index_add_format (GstIndex *index, gint id, GstFormat format);
-#endif
-
-static
-GstIndexEntry* gst_index_add_associationv (GstIndex * index, gint id, GstIndexAssociationFlags flags,
- gint n, const GstIndexAssociation * list);
-#if 0
-GstIndexEntry* gst_index_add_association (GstIndex *index, gint id, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value, ...)
-GstIndexEntry* gst_index_add_object (GstIndex *index, gint id, gchar *key,
- GType type, gpointer object);
-#endif
-
-static
-GstIndexEntry* gst_index_add_id (GstIndex *index, gint id,
- gchar *description);
-
-static
-GstIndexEntry* gst_index_get_assoc_entry (GstIndex *index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value);
-static
-GstIndexEntry* gst_index_get_assoc_entry_full (GstIndex *index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value,
- GCompareDataFunc func,
- gpointer user_data);
-
-/* working with index entries */
-static
-GType gst_index_entry_get_type (void);
-static
-GstIndexEntry * gst_index_entry_copy (GstIndexEntry *entry);
-static
-void gst_index_entry_free (GstIndexEntry *entry);
-static
-gboolean gst_index_entry_assoc_map (GstIndexEntry *entry,
- GstFormat format, gint64 *value);
-
-G_END_DECLS
-
-#endif /* __GST_INDEX_H__ */
diff --git a/libs/gst/base/gstmemindex.c b/libs/gst/base/gstmemindex.c
deleted file mode 100644
index b667447523..0000000000
--- a/libs/gst/base/gstmemindex.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <gst/gst.h>
-
-#define GST_TYPE_MEM_INDEX \
- (gst_index_get_type ())
-#define GST_MEM_INDEX(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MEM_INDEX, GstMemIndex))
-#define GST_MEM_INDEX_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MEM_INDEX, GstMemIndexClass))
-#define GST_IS_MEM_INDEX(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MEM_INDEX))
-#define GST_IS_MEM_INDEX_CLASS(klass) \
- (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MEM_INDEX))
-
-/*
- * Object model:
- *
- * All entries are simply added to a GList first. Then we build
- * an index to each entry for each id/format
- *
- *
- * memindex
- * -----------------------------...
- * ! !
- * id1 id2
- * ------------
- * ! !
- * format1 format2
- * ! !
- * GTree GTree
- *
- *
- * The memindex creates a MemIndexId object for each writer id, a
- * Hashtable is kept to map the id to the MemIndexId
- *
- * The MemIndexId keeps a MemIndexFormatIndex for each format the
- * specific writer wants indexed.
- *
- * The MemIndexFormatIndex keeps all the values of the particular
- * format in a GTree, The values of the GTree point back to the entry.
- *
- * Finding a value for an id/format requires locating the correct GTree,
- * then do a lookup in the Tree to get the required value.
- */
-
-typedef struct
-{
- GstFormat format;
- gint offset;
- GTree *tree;
-}
-GstMemIndexFormatIndex;
-
-typedef struct
-{
- gint id;
- GHashTable *format_index;
-}
-GstMemIndexId;
-
-typedef struct _GstMemIndex GstMemIndex;
-typedef struct _GstMemIndexClass GstMemIndexClass;
-
-struct _GstMemIndex
-{
- GstIndex parent;
-
- GList *associations;
-
- GHashTable *id_index;
-};
-
-struct _GstMemIndexClass
-{
- GstIndexClass parent_class;
-};
-
-static void gst_mem_index_finalize (GObject * object);
-
-static void gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry);
-static GstIndexEntry *gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
- GstIndexLookupMethod method, GstIndexAssociationFlags flags,
- GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data);
-
-#define CLASS(mem_index) GST_MEM_INDEX_CLASS (G_OBJECT_GET_CLASS (mem_index))
-
-static GType gst_mem_index_get_type (void);
-
-G_DEFINE_TYPE (GstMemIndex, gst_mem_index, GST_TYPE_INDEX);
-
-static void
-gst_mem_index_class_init (GstMemIndexClass * klass)
-{
- GObjectClass *gobject_class;
- GstIndexClass *gstindex_class;
-
- gobject_class = (GObjectClass *) klass;
- gstindex_class = (GstIndexClass *) klass;
-
- gobject_class->finalize = gst_mem_index_finalize;
-
- gstindex_class->add_entry = GST_DEBUG_FUNCPTR (gst_mem_index_add_entry);
- gstindex_class->get_assoc_entry =
- GST_DEBUG_FUNCPTR (gst_mem_index_get_assoc_entry);
-}
-
-static void
-gst_mem_index_init (GstMemIndex * index)
-{
- GST_DEBUG ("created new mem index");
-
- index->associations = NULL;
- index->id_index = g_hash_table_new (g_int_hash, g_int_equal);
-}
-
-static void
-gst_mem_index_free_format (gpointer key, gpointer value, gpointer user_data)
-{
- GstMemIndexFormatIndex *index = (GstMemIndexFormatIndex *) value;
-
- if (index->tree) {
- g_tree_destroy (index->tree);
- }
-
- g_slice_free (GstMemIndexFormatIndex, index);
-}
-
-static void
-gst_mem_index_free_id (gpointer key, gpointer value, gpointer user_data)
-{
- GstMemIndexId *id_index = (GstMemIndexId *) value;
-
- if (id_index->format_index) {
- g_hash_table_foreach (id_index->format_index, gst_mem_index_free_format,
- NULL);
- g_hash_table_destroy (id_index->format_index);
- id_index->format_index = NULL;
- }
-
- g_slice_free (GstMemIndexId, id_index);
-}
-
-static void
-gst_mem_index_finalize (GObject * object)
-{
- GstMemIndex *memindex = GST_MEM_INDEX (object);
-
- /* Delete the trees referencing the associations first */
- if (memindex->id_index) {
- g_hash_table_foreach (memindex->id_index, gst_mem_index_free_id, NULL);
- g_hash_table_destroy (memindex->id_index);
- memindex->id_index = NULL;
- }
-
- /* Then delete the associations themselves */
- if (memindex->associations) {
- g_list_foreach (memindex->associations, (GFunc) gst_index_entry_free, NULL);
- g_list_free (memindex->associations);
- memindex->associations = NULL;
- }
-
- G_OBJECT_CLASS (gst_mem_index_parent_class)->finalize (object);
-}
-
-static void
-gst_mem_index_add_id (GstIndex * index, GstIndexEntry * entry)
-{
- GstMemIndex *memindex = GST_MEM_INDEX (index);
- GstMemIndexId *id_index;
-
- id_index = g_hash_table_lookup (memindex->id_index, &entry->id);
-
- if (!id_index) {
- id_index = g_slice_new0 (GstMemIndexId);
-
- id_index->id = entry->id;
- id_index->format_index = g_hash_table_new (g_int_hash, g_int_equal);
- g_hash_table_insert (memindex->id_index, &id_index->id, id_index);
- }
-}
-
-static gint
-mem_index_compare (gconstpointer a, gconstpointer b, gpointer user_data)
-{
- GstMemIndexFormatIndex *index = user_data;
- gint64 val1, val2;
- gint64 diff;
-
- val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset);
- val2 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) b), index->offset);
-
- diff = (val2 - val1);
-
- return (diff == 0 ? 0 : (diff > 0 ? 1 : -1));
-}
-
-static void
-gst_mem_index_index_format (GstMemIndexId * id_index, GstIndexEntry * entry,
- gint assoc)
-{
- GstMemIndexFormatIndex *index;
- GstFormat *format;
-
- format = &GST_INDEX_ASSOC_FORMAT (entry, assoc);
-
- index = g_hash_table_lookup (id_index->format_index, format);
-
- if (!index) {
- index = g_slice_new0 (GstMemIndexFormatIndex);
-
- index->format = *format;
- index->offset = assoc;
- index->tree = g_tree_new_with_data (mem_index_compare, index);
-
- g_hash_table_insert (id_index->format_index, &index->format, index);
- }
-
- g_tree_insert (index->tree, entry, entry);
-}
-
-static void
-gst_mem_index_add_association (GstIndex * index, GstIndexEntry * entry)
-{
- GstMemIndex *memindex = GST_MEM_INDEX (index);
- GstMemIndexId *id_index;
-
- memindex->associations = g_list_prepend (memindex->associations, entry);
-
- id_index = g_hash_table_lookup (memindex->id_index, &entry->id);
- if (id_index) {
- gint i;
-
- for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
- gst_mem_index_index_format (id_index, entry, i);
- }
- }
-}
-
-static void
-gst_mem_index_add_object (GstIndex * index, GstIndexEntry * entry)
-{
-}
-
-static void
-gst_mem_index_add_format (GstIndex * index, GstIndexEntry * entry)
-{
-}
-
-static void
-gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry)
-{
- GST_LOG_OBJECT (index, "added this entry");
-
- switch (entry->type) {
- case GST_INDEX_ENTRY_ID:
- gst_mem_index_add_id (index, entry);
- break;
- case GST_INDEX_ENTRY_ASSOCIATION:
- gst_mem_index_add_association (index, entry);
- break;
- case GST_INDEX_ENTRY_OBJECT:
- gst_mem_index_add_object (index, entry);
- break;
- case GST_INDEX_ENTRY_FORMAT:
- gst_mem_index_add_format (index, entry);
- break;
- default:
- break;
- }
-}
-
-typedef struct
-{
- gint64 value;
- GstMemIndexFormatIndex *index;
- gboolean exact;
- GstIndexEntry *lower;
- gint64 low_diff;
- GstIndexEntry *higher;
- gint64 high_diff;
-}
-GstMemIndexSearchData;
-
-static gint
-mem_index_search (gconstpointer a, gconstpointer b)
-{
- GstMemIndexSearchData *data = (GstMemIndexSearchData *) b;
- GstMemIndexFormatIndex *index = data->index;
- gint64 val1, val2;
- gint64 diff;
-
- val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset);
- val2 = data->value;
-
- diff = (val1 - val2);
- if (diff == 0)
- return 0;
-
- /* exact matching, don't update low/high */
- if (data->exact)
- return (diff > 0 ? 1 : -1);
-
- if (diff < 0) {
- if (diff > data->low_diff) {
- data->low_diff = diff;
- data->lower = (GstIndexEntry *) a;
- }
- diff = -1;
- } else {
- if (diff < data->high_diff) {
- data->high_diff = diff;
- data->higher = (GstIndexEntry *) a;
- }
- diff = 1;
- }
-
- return diff;
-}
-
-static GstIndexEntry *
-gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
- GstIndexLookupMethod method,
- GstIndexAssociationFlags flags,
- GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
-{
- GstMemIndex *memindex = GST_MEM_INDEX (index);
- GstMemIndexId *id_index;
- GstMemIndexFormatIndex *format_index;
- GstIndexEntry *entry;
- GstMemIndexSearchData data;
-
- id_index = g_hash_table_lookup (memindex->id_index, &id);
- if (!id_index)
- return NULL;
-
- format_index = g_hash_table_lookup (id_index->format_index, &format);
- if (!format_index)
- return NULL;
-
- data.value = value;
- data.index = format_index;
- data.exact = (method == GST_INDEX_LOOKUP_EXACT);
-
- /* setup data for low/high checks if we are not looking
- * for an exact match */
- if (!data.exact) {
- data.low_diff = G_MININT64;
- data.lower = NULL;
- data.high_diff = G_MAXINT64;
- data.higher = NULL;
- }
-
- entry = g_tree_search (format_index->tree, mem_index_search, &data);
-
- /* get the low/high values if we're not exact */
- if (entry == NULL && !data.exact) {
- if (method == GST_INDEX_LOOKUP_BEFORE)
- entry = data.lower;
- else if (method == GST_INDEX_LOOKUP_AFTER) {
- entry = data.higher;
- }
- }
-
- if (entry && ((GST_INDEX_ASSOC_FLAGS (entry) & flags) != flags)) {
- if (method != GST_INDEX_LOOKUP_EXACT) {
- GList *l_entry = g_list_find (memindex->associations, entry);
-
- entry = NULL;
-
- while (l_entry) {
- entry = (GstIndexEntry *) l_entry->data;
-
- if (entry->id == id && (GST_INDEX_ASSOC_FLAGS (entry) & flags) == flags)
- break;
-
- if (method == GST_INDEX_LOOKUP_BEFORE)
- l_entry = g_list_next (l_entry);
- else if (method == GST_INDEX_LOOKUP_AFTER) {
- l_entry = g_list_previous (l_entry);
- }
- }
- } else {
- entry = NULL;
- }
- }
-
- return entry;
-}
-
-#if 0
-gboolean
-gst_mem_index_plugin_init (GstPlugin * plugin)
-{
- GstIndexFactory *factory;
-
- factory = gst_index_factory_new ("memindex",
- "A index that stores entries in memory", gst_mem_index_get_type ());
-
- if (factory == NULL) {
- g_warning ("failed to create memindex factory");
- return FALSE;
- }
-
- GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name;
- GST_PLUGIN_FEATURE (factory)->loaded = TRUE;
-
- gst_registry_add_feature (gst_registry_get_default (),
- GST_PLUGIN_FEATURE (factory));
-
- return TRUE;
-}
-#endif
diff --git a/libs/gst/base/gstpushsrc.c b/libs/gst/base/gstpushsrc.c
deleted file mode 100644
index db0a6d3328..0000000000
--- a/libs/gst/base/gstpushsrc.c
+++ /dev/null
@@ -1,173 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstpushsrc
- * @title: 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.
- *
- * Subclasses usually operate in a format that is different from the
- * default GST_FORMAT_BYTES format of #GstBaseSrc.
- *
- * Classes extending this base class will usually be scheduled
- * in a push based mode. If the peer accepts to operate without
- * offsets and within the limits of the allowed block size, this
- * class can operate in getrange based mode automatically. To make
- * this possible, the subclass should implement and override the
- * SCHEDULING query.
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "gstpushsrc.h"
-#include "gsttypefindhelper.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_push_src_debug);
-#define GST_CAT_DEFAULT gst_push_src_debug
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (gst_push_src_debug, "pushsrc", 0, \
- "pushsrc element");
-
-#define gst_push_src_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstPushSrc, gst_push_src, GST_TYPE_BASE_SRC, _do_init);
-
-static gboolean gst_push_src_query (GstBaseSrc * src, GstQuery * query);
-static GstFlowReturn gst_push_src_create (GstBaseSrc * bsrc, guint64 offset,
- guint length, GstBuffer ** ret);
-static GstFlowReturn gst_push_src_alloc (GstBaseSrc * bsrc, guint64 offset,
- guint length, GstBuffer ** ret);
-static GstFlowReturn gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset,
- guint length, GstBuffer * ret);
-
-static void
-gst_push_src_class_init (GstPushSrcClass * klass)
-{
- GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass;
-
- gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_push_src_create);
- gstbasesrc_class->alloc = GST_DEBUG_FUNCPTR (gst_push_src_alloc);
- gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_push_src_fill);
- gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_push_src_query);
-}
-
-static void
-gst_push_src_init (GstPushSrc * pushsrc)
-{
- /* nop */
-}
-
-static gboolean
-gst_push_src_query (GstBaseSrc * src, GstQuery * query)
-{
- gboolean ret;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_SCHEDULING:
- {
- /* a pushsrc can by default never operate in pull mode override
- * if you want something different. */
- gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1,
- 0);
- gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
-
- ret = TRUE;
- break;
- }
- default:
- ret = GST_BASE_SRC_CLASS (parent_class)->query (src, query);
- break;
- }
- return ret;
-}
-
-
-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_BASE_SRC_CLASS (parent_class)->create (bsrc, offset, length, ret);
-
- return fret;
-}
-
-static GstFlowReturn
-gst_push_src_alloc (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->alloc)
- fret = pclass->alloc (src, ret);
- else
- fret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, ret);
-
- return fret;
-}
-
-static GstFlowReturn
-gst_push_src_fill (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->fill)
- fret = pclass->fill (src, ret);
- else
- fret = GST_BASE_SRC_CLASS (parent_class)->fill (bsrc, offset, length, ret);
-
- return fret;
-}
diff --git a/libs/gst/base/gstpushsrc.h b/libs/gst/base/gstpushsrc.h
deleted file mode 100644
index 7dd53b6f07..0000000000
--- a/libs/gst/base/gstpushsrc.h
+++ /dev/null
@@ -1,92 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, 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(klass) (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];
-};
-
-/**
- * GstPushSrcClass:
- * @parent_class: Element parent class
- * @create: Ask the subclass to create a buffer. The subclass decides which
- * size this buffer should be. Other then that, refer to
- * #GstBaseSrc<!-- -->.create() for more details. If this method is
- * not implemented, @alloc followed by @fill will be called.
- * @alloc: Ask the subclass to allocate a buffer. The subclass decides which
- * size this buffer should be. The default implementation will create
- * a new buffer from the negotiated allocator.
- * @fill: Ask the subclass to fill the buffer with data.
- *
- * Subclasses can override any of the available virtual methods or not, as
- * needed. At the minimum, the @fill method should be overridden to produce
- * buffers.
- */
-struct _GstPushSrcClass {
- GstBaseSrcClass parent_class;
-
- /* ask the subclass to create a buffer, the default implementation
- * uses alloc and fill */
- GstFlowReturn (*create) (GstPushSrc *src, GstBuffer **buf);
- /* allocate memory for a buffer */
- GstFlowReturn (*alloc) (GstPushSrc *src, GstBuffer **buf);
- /* ask the subclass to fill a buffer */
- GstFlowReturn (*fill) (GstPushSrc *src, GstBuffer *buf);
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_BASE_API
-GType gst_push_src_get_type (void);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPushSrc, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_PUSH_SRC_H__ */
diff --git a/libs/gst/base/gstqueuearray.c b/libs/gst/base/gstqueuearray.c
deleted file mode 100644
index 1cf1747518..0000000000
--- a/libs/gst/base/gstqueuearray.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/* GStreamer
- * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
- * Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
- *
- * gstqueuearray.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstqueuearray
- * @title: GstQueueArray
- * @short_description: Array based queue object
- *
- * #GstQueueArray is an object that provides standard queue functionality
- * based on an array instead of linked lists. This reduces the overhead
- * caused by memory management by a large factor.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <gst/gst.h>
-#include "gstqueuearray.h"
-
-struct _GstQueueArray
-{
- /* < private > */
- guint8 *array;
- guint size;
- guint head;
- guint tail;
- guint length;
- guint elt_size;
- gboolean struct_array;
- GDestroyNotify clear_func;
-};
-
-/**
- * gst_queue_array_new_for_struct: (skip)
- * @struct_size: Size of each element (e.g. structure) in the array
- * @initial_size: Initial size of the new queue
- *
- * Allocates a new #GstQueueArray object for elements (e.g. structures)
- * of size @struct_size, with an initial queue size of @initial_size.
- *
- * Returns: a new #GstQueueArray object
- *
- * Since: 1.6
- */
-GstQueueArray *
-gst_queue_array_new_for_struct (gsize struct_size, guint initial_size)
-{
- GstQueueArray *array;
-
- g_return_val_if_fail (struct_size > 0, NULL);
-
- array = g_slice_new (GstQueueArray);
- array->elt_size = struct_size;
- array->size = initial_size;
- array->array = g_malloc0 (struct_size * initial_size);
- array->head = 0;
- array->tail = 0;
- array->length = 0;
- array->struct_array = TRUE;
- array->clear_func = NULL;
- return array;
-}
-
-/**
- * gst_queue_array_new: (skip)
- * @initial_size: Initial size of the new queue
- *
- * Allocates a new #GstQueueArray object with an initial
- * queue size of @initial_size.
- *
- * Returns: a new #GstQueueArray object
- *
- * Since: 1.2
- */
-GstQueueArray *
-gst_queue_array_new (guint initial_size)
-{
- GstQueueArray *array;
-
- array = gst_queue_array_new_for_struct (sizeof (gpointer), initial_size);
- array->struct_array = FALSE;
- return array;
-}
-
-/**
- * gst_queue_array_free: (skip)
- * @array: a #GstQueueArray object
- *
- * Frees queue @array and all memory associated to it.
- *
- * Since: 1.2
- */
-void
-gst_queue_array_free (GstQueueArray * array)
-{
- g_return_if_fail (array != NULL);
- gst_queue_array_clear (array);
- g_free (array->array);
- g_slice_free (GstQueueArray, array);
-}
-
-/**
- * gst_queue_array_set_clear_func: (skip)
- * @array: a #GstQueueArray object
- * @clear_func: a function to clear an element of @array
- *
- * Sets a function to clear an element of @array.
- *
- * The @clear_func will be called when an element in the array
- * data segment is removed and when the array is freed and data
- * segment is deallocated as well. @clear_func will be passed a
- * pointer to the element to clear, rather than the element itself.
- *
- * Note that in contrast with other uses of #GDestroyNotify
- * functions, @clear_func is expected to clear the contents of
- * the array element it is given, but not free the element itself.
- *
- * Since: 1.16
- */
-void
-gst_queue_array_set_clear_func (GstQueueArray * array,
- GDestroyNotify clear_func)
-{
- g_return_if_fail (array != NULL);
- array->clear_func = clear_func;
-}
-
-static void
-gst_queue_array_clear_idx (GstQueueArray * array, guint idx)
-{
- guint pos;
-
- if (!array->clear_func)
- return;
-
- pos = (idx + array->head) % array->size;
- if (array->struct_array)
- array->clear_func (array->array + pos * array->elt_size);
- else
- array->clear_func (*(gpointer *) (array->array + pos * array->elt_size));
-}
-
-/**
- * gst_queue_array_clear: (skip)
- * @array: a #GstQueueArray object
- *
- * Clears queue @array and frees all memory associated to it.
- *
- * Since: 1.16
- */
-void
-gst_queue_array_clear (GstQueueArray * array)
-{
- g_return_if_fail (array != NULL);
-
- if (array->clear_func != NULL) {
- guint i;
-
- for (i = 0; i < array->length; i++) {
- gst_queue_array_clear_idx (array, i);
- }
- }
-
- array->head = 0;
- array->tail = 0;
- array->length = 0;
-}
-
-/**
- * gst_queue_array_pop_head_struct: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the head of the queue @array and removes it from the queue.
- *
- * Returns: pointer to element or struct, or NULL if @array was empty. The
- * data pointed to by the returned pointer stays valid only as long as
- * the queue array is not modified further!
- *
- * Since: 1.6
- */
-gpointer
-gst_queue_array_pop_head_struct (GstQueueArray * array)
-{
- gpointer p_struct;
- g_return_val_if_fail (array != NULL, NULL);
- /* empty array */
- if (G_UNLIKELY (array->length == 0))
- return NULL;
-
- p_struct = array->array + (array->elt_size * array->head);
-
- array->head++;
- array->head %= array->size;
- array->length--;
-
- return p_struct;
-}
-
-/**
- * gst_queue_array_pop_head: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns and head of the queue @array and removes
- * it from the queue.
- *
- * Returns: The head of the queue
- *
- * Since: 1.2
- */
-gpointer
-gst_queue_array_pop_head (GstQueueArray * array)
-{
- gpointer ret;
- g_return_val_if_fail (array != NULL, NULL);
-
- /* empty array */
- if (G_UNLIKELY (array->length == 0))
- return NULL;
-
- ret = *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
- array->head++;
- array->head %= array->size;
- array->length--;
- return ret;
-}
-
-/**
- * gst_queue_array_peek_head_struct: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the head of the queue @array without removing it from the queue.
- *
- * Returns: pointer to element or struct, or NULL if @array was empty. The
- * data pointed to by the returned pointer stays valid only as long as
- * the queue array is not modified further!
- *
- * Since: 1.6
- */
-gpointer
-gst_queue_array_peek_head_struct (GstQueueArray * array)
-{
- g_return_val_if_fail (array != NULL, NULL);
- /* empty array */
- if (G_UNLIKELY (array->length == 0))
- return NULL;
-
- return array->array + (array->elt_size * array->head);
-}
-
-/**
- * gst_queue_array_peek_head: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the head of the queue @array and does not
- * remove it from the queue.
- *
- * Returns: The head of the queue
- *
- * Since: 1.2
- */
-gpointer
-gst_queue_array_peek_head (GstQueueArray * array)
-{
- g_return_val_if_fail (array != NULL, NULL);
- /* empty array */
- if (G_UNLIKELY (array->length == 0))
- return NULL;
-
- return *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
-}
-
-/**
- * gst_queue_array_peek_nth: (skip)
- *
- * Returns the item at @idx in @array, but does not remove it from the queue.
- *
- * Returns: The item, or %NULL if @idx was out of bounds
- *
- * Since: 1.16
- */
-gpointer
-gst_queue_array_peek_nth (GstQueueArray * array, guint idx)
-{
- g_return_val_if_fail (array != NULL, NULL);
- g_return_val_if_fail (idx < array->length, NULL);
-
- idx = (array->head + idx) % array->size;
-
- return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
-}
-
-/**
- * gst_queue_array_peek_nth_struct: (skip)
- *
- * Returns the item at @idx in @array, but does not remove it from the queue.
- *
- * Returns: The item, or %NULL if @idx was out of bounds
- *
- * Since: 1.16
- */
-gpointer
-gst_queue_array_peek_nth_struct (GstQueueArray * array, guint idx)
-{
- g_return_val_if_fail (array != NULL, NULL);
- g_return_val_if_fail (idx < array->length, NULL);
-
- idx = (array->head + idx) % array->size;
-
- return array->array + (array->elt_size * idx);
-}
-
-static void
-gst_queue_array_do_expand (GstQueueArray * array)
-{
- guint elt_size = array->elt_size;
- /* newsize is 50% bigger */
- guint oldsize = array->size;
- guint newsize = MAX ((3 * oldsize) / 2, oldsize + 1);
-
- /* copy over data */
- if (array->tail != 0) {
- guint8 *array2 = g_malloc0 (elt_size * newsize);
- guint t1 = array->head;
- guint t2 = oldsize - array->head;
-
- /* [0-----TAIL][HEAD------SIZE]
- *
- * We want to end up with
- * [HEAD------------------TAIL][----FREEDATA------NEWSIZE]
- *
- * 1) move [HEAD-----SIZE] part to beginning of new array
- * 2) move [0-------TAIL] part new array, after previous part
- */
-
- memcpy (array2, array->array + (elt_size * array->head), t2 * elt_size);
- memcpy (array2 + t2 * elt_size, array->array, t1 * elt_size);
-
- g_free (array->array);
- array->array = array2;
- array->head = 0;
- } else {
- /* Fast path, we just need to grow the array */
- array->array = g_realloc (array->array, elt_size * newsize);
- memset (array->array + elt_size * oldsize, 0,
- elt_size * (newsize - oldsize));
- }
- array->tail = oldsize;
- array->size = newsize;
-}
-
-/**
- * gst_queue_array_push_element_tail: (skip)
- * @array: a #GstQueueArray object
- * @p_struct: address of element or structure to push to the tail of the queue
- *
- * Pushes the element at address @p_struct to the tail of the queue @array
- * (Copies the contents of a structure of the struct_size specified when
- * creating the queue into the array).
- *
- * Since: 1.6
- */
-void
-gst_queue_array_push_tail_struct (GstQueueArray * array, gpointer p_struct)
-{
- guint elt_size;
-
- g_return_if_fail (p_struct != NULL);
- g_return_if_fail (array != NULL);
- elt_size = array->elt_size;
-
- /* Check if we need to make room */
- if (G_UNLIKELY (array->length == array->size))
- gst_queue_array_do_expand (array);
-
- memcpy (array->array + elt_size * array->tail, p_struct, elt_size);
- array->tail++;
- array->tail %= array->size;
- array->length++;
-}
-
-/**
- * gst_queue_array_push_tail: (skip)
- * @array: a #GstQueueArray object
- * @data: object to push
- *
- * Pushes @data to the tail of the queue @array.
- *
- * Since: 1.2
- */
-void
-gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
-{
- g_return_if_fail (array != NULL);
-
- /* Check if we need to make room */
- if (G_UNLIKELY (array->length == array->size))
- gst_queue_array_do_expand (array);
-
- *(gpointer *) (array->array + sizeof (gpointer) * array->tail) = data;
- array->tail++;
- array->tail %= array->size;
- array->length++;
-}
-
-/**
- * gst_queue_array_peek_tail: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the tail of the queue @array, but does not remove it from the queue.
- *
- * Returns: The tail of the queue
- *
- * Since: 1.14
- */
-gpointer
-gst_queue_array_peek_tail (GstQueueArray * array)
-{
- guint len, idx;
-
- g_return_val_if_fail (array != NULL, NULL);
-
- len = array->length;
-
- /* empty array */
- if (len == 0)
- return NULL;
-
- idx = (array->head + (len - 1)) % array->size;
-
- return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
-}
-
-/**
- * gst_queue_array_peek_tail_struct: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the tail of the queue @array, but does not remove it from the queue.
- *
- * Returns: The tail of the queue
- *
- * Since: 1.14
- */
-gpointer
-gst_queue_array_peek_tail_struct (GstQueueArray * array)
-{
- guint len, idx;
-
- g_return_val_if_fail (array != NULL, NULL);
-
- len = array->length;
-
- /* empty array */
- if (len == 0)
- return NULL;
-
- idx = (array->head + (len - 1)) % array->size;
-
- return array->array + (array->elt_size * idx);
-}
-
-/**
- * gst_queue_array_pop_tail: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the tail of the queue @array and removes
- * it from the queue.
- *
- * Returns: The tail of the queue
- *
- * Since: 1.14
- */
-gpointer
-gst_queue_array_pop_tail (GstQueueArray * array)
-{
- gpointer ret;
- guint len, idx;
-
- g_return_val_if_fail (array != NULL, NULL);
-
- len = array->length;
-
- /* empty array */
- if (len == 0)
- return NULL;
-
- idx = (array->head + (len - 1)) % array->size;
-
- ret = *(gpointer *) (array->array + (sizeof (gpointer) * idx));
-
- array->tail = idx;
- array->length--;
-
- return ret;
-}
-
-/**
- * gst_queue_array_pop_tail_struct: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the tail of the queue @array and removes
- * it from the queue.
- *
- * Returns: The tail of the queue
- *
- * Since: 1.14
- */
-gpointer
-gst_queue_array_pop_tail_struct (GstQueueArray * array)
-{
- gpointer ret;
- guint len, idx;
-
- g_return_val_if_fail (array != NULL, NULL);
-
- len = array->length;
-
- /* empty array */
- if (len == 0)
- return NULL;
-
- idx = (array->head + (len - 1)) % array->size;
-
- ret = array->array + (array->elt_size * idx);
-
- array->tail = idx;
- array->length--;
-
- return ret;
-}
-
-/**
- * gst_queue_array_is_empty: (skip)
- * @array: a #GstQueueArray object
- *
- * Checks if the queue @array is empty.
- *
- * Returns: %TRUE if the queue @array is empty
- *
- * Since: 1.2
- */
-gboolean
-gst_queue_array_is_empty (GstQueueArray * array)
-{
- g_return_val_if_fail (array != NULL, FALSE);
- return (array->length == 0);
-}
-
-
-/**
- * gst_queue_array_drop_struct: (skip)
- * @array: a #GstQueueArray object
- * @idx: index to drop
- * @p_struct: address into which to store the data of the dropped structure, or NULL
- *
- * Drops the queue element at position @idx from queue @array and copies the
- * data of the element or structure that was removed into @p_struct if
- * @p_struct is set (not NULL).
- *
- * Returns: TRUE on success, or FALSE on error
- *
- * Since: 1.6
- */
-gboolean
-gst_queue_array_drop_struct (GstQueueArray * array, guint idx,
- gpointer p_struct)
-{
- int first_item_index, last_item_index;
- guint actual_idx;
- guint elt_size;
-
- g_return_val_if_fail (array != NULL, FALSE);
- actual_idx = (array->head + idx) % array->size;
-
- g_return_val_if_fail (array->length > 0, FALSE);
- g_return_val_if_fail (actual_idx < array->size, FALSE);
-
- elt_size = array->elt_size;
-
- first_item_index = array->head;
-
- /* tail points to the first free spot */
- last_item_index = (array->tail - 1 + array->size) % array->size;
-
- if (p_struct != NULL)
- memcpy (p_struct, array->array + elt_size * actual_idx, elt_size);
-
- /* simple case actual_idx == first item */
- if (actual_idx == first_item_index) {
- /* clear current head position if needed */
- if (p_struct == NULL)
- gst_queue_array_clear_idx (array, idx);
-
- /* move the head plus one */
- array->head++;
- array->head %= array->size;
- array->length--;
- return TRUE;
- }
-
- /* simple case idx == last item */
- if (actual_idx == last_item_index) {
- /* clear current tail position if needed */
- if (p_struct == NULL)
- gst_queue_array_clear_idx (array, idx);
-
- /* move tail minus one, potentially wrapping */
- array->tail = (array->tail - 1 + array->size) % array->size;
- array->length--;
- return TRUE;
- }
-
- /* non-wrapped case */
- if (first_item_index < last_item_index) {
- /* clear idx if needed */
- if (p_struct == NULL)
- gst_queue_array_clear_idx (array, idx);
-
- g_assert (first_item_index < actual_idx && actual_idx < last_item_index);
- /* move everything beyond actual_idx one step towards zero in array */
- memmove (array->array + elt_size * actual_idx,
- array->array + elt_size * (actual_idx + 1),
- (last_item_index - actual_idx) * elt_size);
- /* tail might wrap, ie if tail == 0 (and last_item_index == size) */
- array->tail = (array->tail - 1 + array->size) % array->size;
- array->length--;
- return TRUE;
- }
-
- /* only wrapped cases left */
- g_assert (first_item_index > last_item_index);
-
- if (actual_idx < last_item_index) {
- /* clear idx if needed */
- if (p_struct == NULL)
- gst_queue_array_clear_idx (array, idx);
-
- /* actual_idx is before last_item_index, move data towards zero */
- memmove (array->array + elt_size * actual_idx,
- array->array + elt_size * (actual_idx + 1),
- (last_item_index - actual_idx) * elt_size);
- /* tail should not wrap in this case! */
- g_assert (array->tail > 0);
- array->tail--;
- array->length--;
- return TRUE;
- }
-
- if (actual_idx > first_item_index) {
- /* clear idx if needed */
- if (p_struct == NULL)
- gst_queue_array_clear_idx (array, idx);
-
- /* actual_idx is after first_item_index, move data to higher indices */
- memmove (array->array + elt_size * (first_item_index + 1),
- array->array + elt_size * first_item_index,
- (actual_idx - first_item_index) * elt_size);
- array->head++;
- /* head should not wrap in this case! */
- g_assert (array->head < array->size);
- array->length--;
- return TRUE;
- }
-
- g_return_val_if_reached (FALSE);
-}
-
-/**
- * gst_queue_array_drop_element: (skip)
- * @array: a #GstQueueArray object
- * @idx: index to drop
- *
- * Drops the queue element at position @idx from queue @array.
- *
- * Returns: the dropped element
- *
- * Since: 1.2
- */
-gpointer
-gst_queue_array_drop_element (GstQueueArray * array, guint idx)
-{
- gpointer ptr;
-
- if (!gst_queue_array_drop_struct (array, idx, &ptr))
- return NULL;
-
- return ptr;
-}
-
-/**
- * gst_queue_array_find: (skip)
- * @array: a #GstQueueArray object
- * @func: (allow-none): comparison function, or %NULL to find @data by value
- * @data: data for comparison function
- *
- * Finds an element in the queue @array, either by comparing every element
- * with @func or by looking up @data if no compare function @func is provided,
- * and returning the index of the found element.
- *
- * Returns: Index of the found element or -1 if nothing was found.
- *
- * Since: 1.2
- */
-guint
-gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
-{
- gpointer p_element;
- guint elt_size;
- guint i;
-
- /* For struct arrays we need to implement this differently so that
- * the user gets a pointer to the element data not the dereferenced
- * pointer itself */
-
- g_return_val_if_fail (array != NULL, -1);
- g_return_val_if_fail (array->struct_array == FALSE, -1);
-
- elt_size = array->elt_size;
-
- if (func != NULL) {
- /* Scan from head to tail */
- for (i = 0; i < array->length; i++) {
- p_element = array->array + ((i + array->head) % array->size) * elt_size;
- if (func (*(gpointer *) p_element, data) == 0)
- return i;
- }
- } else {
- for (i = 0; i < array->length; i++) {
- p_element = array->array + ((i + array->head) % array->size) * elt_size;
- if (*(gpointer *) p_element == data)
- return i;
- }
- }
-
- return -1;
-}
-
-/**
- * gst_queue_array_get_length: (skip)
- * @array: a #GstQueueArray object
- *
- * Returns the length of the queue @array
- *
- * Returns: the length of the queue @array.
- *
- * Since: 1.2
- */
-guint
-gst_queue_array_get_length (GstQueueArray * array)
-{
- g_return_val_if_fail (array != NULL, 0);
- return array->length;
-}
diff --git a/libs/gst/base/gstqueuearray.h b/libs/gst/base/gstqueuearray.h
deleted file mode 100644
index 77edec0990..0000000000
--- a/libs/gst/base/gstqueuearray.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* GStreamer
- * Copyright (C) 2009-2010 Edward Hervey <bilboed@bilboed.com>
- *
- * gstqueuearray.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <glib.h>
-
-#ifndef __GST_QUEUE_ARRAY_H__
-#define __GST_QUEUE_ARRAY_H__
-
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstQueueArray: (skip)
- */
-typedef struct _GstQueueArray GstQueueArray;
-
-GST_BASE_API
-GstQueueArray * gst_queue_array_new (guint initial_size);
-
-GST_BASE_API
-void gst_queue_array_free (GstQueueArray * array);
-
-GST_BASE_API
-void gst_queue_array_set_clear_func (GstQueueArray *array,
- GDestroyNotify clear_func);
-
-GST_BASE_API
-void gst_queue_array_clear (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_pop_head (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_head (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_nth (GstQueueArray * array, guint idx);
-
-GST_BASE_API
-gpointer gst_queue_array_pop_tail (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_tail (GstQueueArray * array);
-
-GST_BASE_API
-void gst_queue_array_push_tail (GstQueueArray * array,
- gpointer data);
-GST_BASE_API
-gboolean gst_queue_array_is_empty (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_drop_element (GstQueueArray * array,
- guint idx);
-GST_BASE_API
-guint gst_queue_array_find (GstQueueArray * array,
- GCompareFunc func,
- gpointer data);
-GST_BASE_API
-guint gst_queue_array_get_length (GstQueueArray * array);
-
-/* Functions for use with structures */
-
-GST_BASE_API
-GstQueueArray * gst_queue_array_new_for_struct (gsize struct_size,
- guint initial_size);
-GST_BASE_API
-void gst_queue_array_push_tail_struct (GstQueueArray * array,
- gpointer p_struct);
-GST_BASE_API
-gpointer gst_queue_array_pop_head_struct (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_head_struct (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_nth_struct (GstQueueArray * array, guint idx);
-
-GST_BASE_API
-gboolean gst_queue_array_drop_struct (GstQueueArray * array,
- guint idx,
- gpointer p_struct);
-GST_BASE_API
-gpointer gst_queue_array_pop_tail_struct (GstQueueArray * array);
-
-GST_BASE_API
-gpointer gst_queue_array_peek_tail_struct (GstQueueArray * array);
-
-G_END_DECLS
-
-#endif
diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c
deleted file mode 100644
index 56003d500a..0000000000
--- a/libs/gst/base/gsttypefindhelper.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) 2000,2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gsttypefindhelper
- * @title: GstTypeFindHelper
- * @short_description: Utility functions for typefinding
- *
- * Utility functions for elements doing typefinding:
- * gst_type_find_helper() does typefinding in pull mode, while
- * gst_type_find_helper_for_buffer() is useful for elements needing to do
- * typefinding in push mode from a chain function.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "gsttypefindhelper.h"
-
-/* ********************** typefinding in pull mode ************************ */
-
-static void
-helper_find_suggest (gpointer data, guint probability, GstCaps * caps);
-
-typedef struct
-{
- GstBuffer *buffer;
- GstMapInfo map;
-} GstMappedBuffer;
-
-typedef struct
-{
- GSList *buffers; /* buffer cache */
- guint64 size;
- guint64 last_offset;
- GstTypeFindHelperGetRangeFunction func;
- GstTypeFindProbability best_probability;
- GstCaps *caps;
- GstTypeFindFactory *factory; /* for logging */
- GstObject *obj; /* for logging */
- GstObject *parent;
- GstFlowReturn flow_ret;
-} GstTypeFindHelper;
-
-/*
- * helper_find_peek:
- * @data: helper data struct
- * @off: stream offset
- * @size: block size
- *
- * Get data pointer within a stream. Keeps a cache of read buffers (partly
- * for performance reasons, but mostly because pointers returned by us need
- * to stay valid until typefinding has finished)
- *
- * Returns: (nullable): address of the data or %NULL if buffer does not cover
- * the requested range.
- */
-static const guint8 *
-helper_find_peek (gpointer data, gint64 offset, guint size)
-{
- GstTypeFindHelper *helper;
- GstBuffer *buffer;
- GSList *insert_pos = NULL;
- gsize buf_size;
- guint64 buf_offset;
- GstMappedBuffer *bmap;
-#if 0
- GstCaps *caps;
-#endif
-
- helper = (GstTypeFindHelper *) data;
-
- GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT
- ", %u)", GST_OBJECT_NAME (helper->factory), offset, size);
-
- if (size == 0)
- return NULL;
-
- if (offset < 0) {
- if (helper->size == -1 || helper->size < -offset)
- return NULL;
-
- offset += helper->size;
- }
-
- /* see if we have a matching buffer already in our list */
- if (size > 0 && offset <= helper->last_offset) {
- GSList *walk;
-
- for (walk = helper->buffers; walk; walk = walk->next) {
- GstMappedBuffer *bmp = (GstMappedBuffer *) walk->data;
- GstBuffer *buf = GST_BUFFER_CAST (bmp->buffer);
-
- buf_offset = GST_BUFFER_OFFSET (buf);
- buf_size = bmp->map.size;
-
- /* buffers are kept sorted by end offset (highest first) in the list, so
- * at this point we save the current position and stop searching if
- * we're after the searched end offset */
- if (buf_offset <= offset) {
- if ((offset + size) < (buf_offset + buf_size)) {
- /* must already have been mapped before */
- return (guint8 *) bmp->map.data + (offset - buf_offset);
- }
- } else if (offset + size >= buf_offset + buf_size) {
- insert_pos = walk;
- break;
- }
- }
- }
-
- buffer = NULL;
- /* some typefinders go in 1 byte steps over 1k of data and request
- * small buffers. It is really inefficient to pull each time, and pulling
- * a larger chunk is almost free. Trying to pull a larger chunk at the end
- * of the file is also not a problem here, we'll just get a truncated buffer
- * in that case (and we'll have to double-check the size we actually get
- * anyway, see below) */
- helper->flow_ret =
- helper->func (helper->obj, helper->parent, offset, MAX (size, 4096),
- &buffer);
-
- if (helper->flow_ret != GST_FLOW_OK)
- goto error;
-
-#if 0
- caps = GST_BUFFER_CAPS (buffer);
-
- if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
- GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability",
- caps);
-
- gst_caps_replace (&helper->caps, caps);
- helper->best_probability = GST_TYPE_FIND_MAXIMUM;
-
- gst_buffer_unref (buffer);
- return NULL;
- }
-#endif
-
- /* getrange might silently return shortened buffers at the end of a file,
- * we must, however, always return either the full requested data or %NULL */
- buf_offset = GST_BUFFER_OFFSET (buffer);
- buf_size = gst_buffer_get_size (buffer);
-
- if (buf_size < size) {
- GST_DEBUG ("dropping short buffer of size %" G_GSIZE_FORMAT ","
- "requested size was %u", buf_size, size);
- gst_buffer_unref (buffer);
- return NULL;
- }
-
- if (buf_offset != -1 && buf_offset != offset) {
- GST_DEBUG ("dropping buffer with unexpected offset %" G_GUINT64_FORMAT ", "
- "expected offset was %" G_GUINT64_FORMAT, buf_offset, offset);
- gst_buffer_unref (buffer);
- return NULL;
- }
-
- bmap = g_slice_new0 (GstMappedBuffer);
-
- if (!gst_buffer_map (buffer, &bmap->map, GST_MAP_READ))
- goto map_failed;
-
- bmap->buffer = buffer;
-
- if (insert_pos) {
- helper->buffers = g_slist_insert_before (helper->buffers, insert_pos, bmap);
- } else {
- /* if insert_pos is not set, our offset is bigger than the largest offset
- * we have so far; since we keep the list sorted with highest offsets
- * first, we need to prepend the buffer to the list */
- helper->last_offset = GST_BUFFER_OFFSET (buffer) + buf_size;
- helper->buffers = g_slist_prepend (helper->buffers, bmap);
- }
-
- return bmap->map.data;
-
-error:
- {
- GST_INFO ("typefind function returned: %s",
- gst_flow_get_name (helper->flow_ret));
- return NULL;
- }
-map_failed:
- {
- GST_ERROR ("map failed");
- gst_buffer_unref (buffer);
- g_slice_free (GstMappedBuffer, bmap);
- return NULL;
- }
-}
-
-/*
- * helper_find_suggest:
- * @data: helper data struct
- * @probability: probability of the match
- * @caps: caps of the type
- *
- * If given @probability is higher, replace previously store caps.
- */
-static void
-helper_find_suggest (gpointer data, guint probability, GstCaps * caps)
-{
- GstTypeFindHelper *helper = (GstTypeFindHelper *) data;
-
- GST_LOG_OBJECT (helper->obj,
- "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
- GST_OBJECT_NAME (helper->factory), probability, caps);
-
- if (probability > helper->best_probability) {
- gst_caps_replace (&helper->caps, caps);
- helper->best_probability = probability;
- }
-}
-
-static guint64
-helper_find_get_length (gpointer data)
-{
- GstTypeFindHelper *helper = (GstTypeFindHelper *) data;
-
- GST_LOG_OBJECT (helper->obj, "'%s' called get_length, returning %"
- G_GUINT64_FORMAT, GST_OBJECT_NAME (helper->factory), helper->size);
-
- return helper->size;
-}
-
-static GList *
-prioritize_extension (GstObject * obj, GList * type_list,
- const gchar * extension)
-{
- gint pos = 0;
- GList *next, *l;
-
- if (!extension)
- return type_list;
-
- /* move the typefinders for the extension first in the list. The idea is that
- * when one of them returns MAX we don't need to search further as there is a
- * very high chance we got the right type. */
-
- GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head", extension);
-
- for (l = type_list; l; l = next) {
- const gchar *const *ext;
- GstTypeFindFactory *factory;
-
- next = l->next;
-
- factory = GST_TYPE_FIND_FACTORY (l->data);
-
- ext = gst_type_find_factory_get_extensions (factory);
- if (ext == NULL)
- continue;
-
- GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
- GST_OBJECT_NAME (factory), extension);
-
- while (*ext != NULL) {
- if (strcmp (*ext, extension) == 0) {
- /* found extension, move in front */
- GST_LOG_OBJECT (obj, "moving typefind for extension %s to head",
- extension);
- /* remove entry from list */
- type_list = g_list_delete_link (type_list, l);
- /* insert at the position */
- type_list = g_list_insert (type_list, factory, pos);
- /* next element will be inserted after this one */
- pos++;
- break;
- }
- ++ext;
- }
- }
-
- return type_list;
-}
-
-/**
- * gst_type_find_helper_get_range:
- * @obj: A #GstObject that will be passed as first argument to @func
- * @parent: (allow-none): the parent of @obj or %NULL
- * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
- * be used to access data at random offsets when doing the typefinding
- * @size: The length in bytes
- * @extension: (allow-none): extension of the media, or %NULL
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
- * however, this function will use the specified function @func to obtain the
- * data needed by the typefind functions, rather than operating on a given
- * source pad. This is useful mostly for elements like tag demuxers which
- * strip off data at the beginning and/or end of a file and want to typefind
- * the stripped data stream before adding their own source pad (the specified
- * callback can then call the upstream peer pad with offsets adjusted for the
- * tag size, for example).
- *
- * When @extension is not %NULL, this function will first try the typefind
- * functions for the given extension, which might speed up the typefinding
- * in many cases.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data
- * stream. Returns %NULL if no #GstCaps matches the data stream.
- */
-GstCaps *
-gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
- GstTypeFindHelperGetRangeFunction func, guint64 size,
- const gchar * extension, GstTypeFindProbability * prob)
-{
- GstCaps *caps = NULL;
-
- gst_type_find_helper_get_range_full (obj, parent, func, size, extension,
- &caps, prob);
-
- return caps;
-}
-
-/**
- * gst_type_find_helper_get_range_full:
- * @obj: A #GstObject that will be passed as first argument to @func
- * @parent: (allow-none): the parent of @obj or %NULL
- * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
- * be used to access data at random offsets when doing the typefinding
- * @size: The length in bytes
- * @extension: (allow-none): extension of the media, or %NULL
- * @caps: (out) (transfer full): returned caps
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
- * however, this function will use the specified function @func to obtain the
- * data needed by the typefind functions, rather than operating on a given
- * source pad. This is useful mostly for elements like tag demuxers which
- * strip off data at the beginning and/or end of a file and want to typefind
- * the stripped data stream before adding their own source pad (the specified
- * callback can then call the upstream peer pad with offsets adjusted for the
- * tag size, for example).
- *
- * When @extension is not %NULL, this function will first try the typefind
- * functions for the given extension, which might speed up the typefinding
- * in many cases.
- *
- * Returns: the last %GstFlowReturn from pulling a buffer or %GST_FLOW_OK if
- * typefinding was successful.
- *
- * Since: 1.14.3
- */
-GstFlowReturn
-gst_type_find_helper_get_range_full (GstObject * obj, GstObject * parent,
- GstTypeFindHelperGetRangeFunction func, guint64 size,
- const gchar * extension, GstCaps ** caps, GstTypeFindProbability * prob)
-{
- GstTypeFindHelper helper;
- GstTypeFind find;
- GSList *walk;
- GList *l, *type_list;
- GstCaps *result = NULL;
-
- g_return_val_if_fail (GST_IS_OBJECT (obj), GST_FLOW_ERROR);
- g_return_val_if_fail (func != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (caps != NULL, GST_FLOW_ERROR);
-
- *caps = NULL;
-
- helper.buffers = NULL;
- helper.size = size;
- helper.last_offset = 0;
- helper.func = func;
- helper.best_probability = GST_TYPE_FIND_NONE;
- helper.caps = NULL;
- helper.obj = obj;
- helper.parent = parent;
- helper.flow_ret = GST_FLOW_OK;
-
- find.data = &helper;
- find.peek = helper_find_peek;
- find.suggest = helper_find_suggest;
-
- if (size == 0 || size == (guint64) - 1) {
- find.get_length = NULL;
- } else {
- find.get_length = helper_find_get_length;
- }
-
- type_list = gst_type_find_factory_get_list ();
- type_list = prioritize_extension (obj, type_list, extension);
-
- for (l = type_list; l; l = l->next) {
- helper.factory = GST_TYPE_FIND_FACTORY (l->data);
- gst_type_find_factory_call_function (helper.factory, &find);
- if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM) {
- /* Any other flow return can be ignored here, we found
- * something before any error with highest probability */
- helper.flow_ret = GST_FLOW_OK;
- break;
- } else if (helper.flow_ret != GST_FLOW_OK
- && helper.flow_ret != GST_FLOW_EOS) {
- /* We had less than maximum probability and an error, don't return
- * any caps as they might be with a lower probability than what
- * we would've gotten when continuing if there was no error */
- gst_caps_replace (&helper.caps, NULL);
- break;
- }
- }
- gst_plugin_feature_list_free (type_list);
-
- for (walk = helper.buffers; walk; walk = walk->next) {
- GstMappedBuffer *bmap = (GstMappedBuffer *) walk->data;
-
- gst_buffer_unmap (bmap->buffer, &bmap->map);
- gst_buffer_unref (bmap->buffer);
- g_slice_free (GstMappedBuffer, bmap);
- }
- g_slist_free (helper.buffers);
-
- if (helper.best_probability > 0)
- result = helper.caps;
-
- if (prob)
- *prob = helper.best_probability;
-
- *caps = result;
- if (helper.flow_ret == GST_FLOW_EOS) {
- /* Some typefinder might've tried to read too much, if we
- * didn't get any meaningful caps because of that this is
- * just a normal error */
- helper.flow_ret = GST_FLOW_ERROR;
- }
-
- GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
- result, (guint) helper.best_probability);
-
- return helper.flow_ret;
-}
-
-/**
- * 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.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): 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)
-{
- GstTypeFindHelperGetRangeFunction func;
-
- g_return_val_if_fail (GST_IS_OBJECT (src), NULL);
- g_return_val_if_fail (GST_PAD_GETRANGEFUNC (src) != NULL, NULL);
-
- func = (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (src));
-
- return gst_type_find_helper_get_range (GST_OBJECT (src),
- GST_OBJECT_PARENT (src), func, size, NULL, NULL);
-}
-
-/* ********************** typefinding for buffers ************************* */
-
-typedef struct
-{
- const guint8 *data; /* buffer data */
- gsize size;
- GstTypeFindProbability best_probability;
- GstCaps *caps;
- GstTypeFindFactory *factory; /* for logging */
- GstObject *obj; /* for logging */
-} GstTypeFindBufHelper;
-
-/*
- * buf_helper_find_peek:
- * @data: helper data struct
- * @off: stream offset
- * @size: block size
- *
- * Get data pointer within a buffer.
- *
- * Returns: (nullable): address inside the buffer or %NULL if buffer does not
- * cover the requested range.
- */
-static const guint8 *
-buf_helper_find_peek (gpointer data, gint64 off, guint size)
-{
- GstTypeFindBufHelper *helper;
-
- helper = (GstTypeFindBufHelper *) data;
- GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
- GST_OBJECT_NAME (helper->factory), off, size);
-
- if (size == 0)
- return NULL;
-
- if (off < 0) {
- GST_LOG_OBJECT (helper->obj, "'%s' wanted to peek at end; not supported",
- GST_OBJECT_NAME (helper->factory));
- return NULL;
- }
-
- /* If we request beyond the available size, we're sure we can't return
- * anything regardless of the requested offset */
- if (size > helper->size)
- return NULL;
-
- /* Only return data if there's enough room left for the given offset.
- * This is the same as "if (off + size <= helper->size)" except that
- * it doesn't exceed type limits */
- if (off <= helper->size - size)
- return helper->data + off;
-
- return NULL;
-}
-
-/*
- * buf_helper_find_suggest:
- * @data: helper data struct
- * @probability: probability of the match
- * @caps: caps of the type
- *
- * If given @probability is higher, replace previously store caps.
- */
-static void
-buf_helper_find_suggest (gpointer data, guint probability, GstCaps * caps)
-{
- GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data;
-
- GST_LOG_OBJECT (helper->obj,
- "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
- GST_OBJECT_NAME (helper->factory), probability, caps);
-
- /* Note: not >= as we call typefinders in order of rank, highest first */
- if (probability > helper->best_probability) {
- gst_caps_replace (&helper->caps, caps);
- helper->best_probability = probability;
- }
-}
-
-/**
- * gst_type_find_helper_for_data:
- * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
- * @data: (transfer none) (array length=size): * a pointer with data to typefind
- * @size: the size of @data
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Tries to find what type of data is contained in the given @data, the
- * assumption being that the data represents the beginning of the stream or
- * file.
- *
- * All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
- * typefinding is stopped immediately and the found caps will be returned
- * right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or %NULL if
- * the content of @data could not be identified.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data,
- * or %NULL if no type could be found. The caller should free the caps
- * returned with gst_caps_unref().
- */
-GstCaps *
-gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size,
- GstTypeFindProbability * prob)
-{
- return gst_type_find_helper_for_data_with_extension (obj, data, size, NULL,
- prob);
-}
-
-/**
- * gst_type_find_helper_for_data_with_extension:
- * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
- * @data: (transfer none) (array length=size): * a pointer with data to typefind
- * @size: the size of @data
- * @extension: (allow-none): extension of the media, or %NULL
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Tries to find what type of data is contained in the given @data, the
- * assumption being that the data represents the beginning of the stream or
- * file.
- *
- * All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
- * typefinding is stopped immediately and the found caps will be returned
- * right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or %NULL if
- * the content of @data could not be identified.
- *
- * When @extension is not %NULL, this function will first try the typefind
- * functions for the given extension, which might speed up the typefinding
- * in many cases.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data,
- * or %NULL if no type could be found. The caller should free the caps
- * returned with gst_caps_unref().
- *
- * Since: 1.16
- *
- */
-GstCaps *
-gst_type_find_helper_for_data_with_extension (GstObject * obj,
- const guint8 * data, gsize size, const gchar * extension,
- GstTypeFindProbability * prob)
-{
- GstTypeFindBufHelper helper;
- GstTypeFind find;
- GList *l, *type_list;
- GstCaps *result = NULL;
-
- g_return_val_if_fail (data != NULL, NULL);
-
- helper.data = data;
- helper.size = size;
- helper.best_probability = GST_TYPE_FIND_NONE;
- helper.caps = NULL;
- helper.obj = obj;
-
- if (helper.data == NULL || helper.size == 0)
- return NULL;
-
- find.data = &helper;
- find.peek = buf_helper_find_peek;
- find.suggest = buf_helper_find_suggest;
- find.get_length = NULL;
-
- type_list = gst_type_find_factory_get_list ();
- type_list = prioritize_extension (obj, type_list, extension);
-
- for (l = type_list; l; l = l->next) {
- helper.factory = GST_TYPE_FIND_FACTORY (l->data);
- gst_type_find_factory_call_function (helper.factory, &find);
- if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
- break;
- }
- gst_plugin_feature_list_free (type_list);
-
- if (helper.best_probability > 0)
- result = helper.caps;
-
- if (prob)
- *prob = helper.best_probability;
-
- GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
- result, (guint) helper.best_probability);
-
- return result;
-}
-
-/**
- * gst_type_find_helper_for_buffer:
- * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
- * @buf: (in) (transfer none): a #GstBuffer with data to typefind
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Tries to find what type of data is contained in the given #GstBuffer, the
- * assumption being that the buffer represents the beginning of the stream or
- * file.
- *
- * All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
- * typefinding is stopped immediately and the found caps will be returned
- * right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or %NULL if
- * the content of the buffer could not be identified.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data,
- * or %NULL if no type could be found. The caller should free the caps
- * returned with gst_caps_unref().
- */
-GstCaps *
-gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
- GstTypeFindProbability * prob)
-{
- return gst_type_find_helper_for_buffer_with_extension (obj, buf, NULL, prob);
-}
-
-/**
- * gst_type_find_helper_for_buffer_with_extension:
- * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
- * @buf: (in) (transfer none): a #GstBuffer with data to typefind
- * @extension: (allow-none): extension of the media, or %NULL
- * @prob: (out) (allow-none): location to store the probability of the found
- * caps, or %NULL
- *
- * Tries to find what type of data is contained in the given #GstBuffer, the
- * assumption being that the buffer represents the beginning of the stream or
- * file.
- *
- * All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
- * typefinding is stopped immediately and the found caps will be returned
- * right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or %NULL if
- * the content of the buffer could not be identified.
- *
- * When @extension is not %NULL, this function will first try the typefind
- * functions for the given extension, which might speed up the typefinding
- * in many cases.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data,
- * or %NULL if no type could be found. The caller should free the caps
- * returned with gst_caps_unref().
- *
- * Since: 1.16
- *
- */
-GstCaps *
-gst_type_find_helper_for_buffer_with_extension (GstObject * obj,
- GstBuffer * buf, const gchar * extension, GstTypeFindProbability * prob)
-{
- GstCaps *result;
- GstMapInfo info;
-
- g_return_val_if_fail (buf != NULL, NULL);
- g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
- g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
- GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);
-
- if (!gst_buffer_map (buf, &info, GST_MAP_READ))
- return NULL;
- result =
- gst_type_find_helper_for_data_with_extension (obj, info.data, info.size,
- extension, prob);
- gst_buffer_unmap (buf, &info);
-
- return result;
-}
-
-/**
- * gst_type_find_helper_for_extension:
- * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
- * @extension: an extension
- *
- * Tries to find the best #GstCaps associated with @extension.
- *
- * All available typefinders will be checked against the extension in order
- * of rank. The caps of the first typefinder that can handle @extension will be
- * returned.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full) (nullable): the #GstCaps corresponding to
- * @extension, or %NULL if no type could be found. The caller should free
- * the caps returned with gst_caps_unref().
- */
-GstCaps *
-gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension)
-{
- GList *l, *type_list;
- GstCaps *result = NULL;
-
- g_return_val_if_fail (extension != NULL, NULL);
-
- GST_LOG_OBJECT (obj, "finding caps for extension %s", extension);
-
- type_list = gst_type_find_factory_get_list ();
-
- for (l = type_list; l; l = g_list_next (l)) {
- GstTypeFindFactory *factory;
- const gchar *const *ext;
-
- factory = GST_TYPE_FIND_FACTORY (l->data);
-
- /* we only want to check those factories without a function */
- if (gst_type_find_factory_has_function (factory))
- continue;
-
- /* get the extension that this typefind factory can handle */
- ext = gst_type_find_factory_get_extensions (factory);
- if (ext == NULL)
- continue;
-
- /* there are extension, see if one of them matches the requested
- * extension */
- while (*ext != NULL) {
- if (strcmp (*ext, extension) == 0) {
- /* we found a matching extension, take the caps */
- if ((result = gst_type_find_factory_get_caps (factory))) {
- gst_caps_ref (result);
- goto done;
- }
- }
- ++ext;
- }
- }
-done:
- gst_plugin_feature_list_free (type_list);
-
- GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result);
-
- return result;
-}
diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h
deleted file mode 100644
index bda346cac1..0000000000
--- a/libs/gst/base/gsttypefindhelper.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) 2000,2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_TYPEFINDHELPER_H__
-#define __GST_TYPEFINDHELPER_H__
-
-#include <gst/gst.h>
-#include <gst/base/base-prelude.h>
-
-G_BEGIN_DECLS
-
-GST_BASE_API
-GstCaps * gst_type_find_helper (GstPad *src, guint64 size);
-
-GST_BASE_API
-GstCaps * gst_type_find_helper_for_data (GstObject *obj,
- const guint8 *data,
- gsize size,
- GstTypeFindProbability *prob);
-
-GST_BASE_API
-GstCaps * gst_type_find_helper_for_data_with_extension (GstObject *obj,
- const guint8 *data,
- gsize size,
- const gchar *extension,
- GstTypeFindProbability *prob);
-
-GST_BASE_API
-GstCaps * gst_type_find_helper_for_buffer (GstObject *obj,
- GstBuffer *buf,
- GstTypeFindProbability *prob);
-
-GST_BASE_API
-GstCaps * gst_type_find_helper_for_buffer_with_extension (GstObject *obj,
- GstBuffer *buf,
- const gchar *extension,
- GstTypeFindProbability *prob);
-
-GST_BASE_API
-GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
- const gchar * extension);
-
-/**
- * GstTypeFindHelperGetRangeFunction:
- * @obj: a #GstObject that will handle the getrange request
- * @parent: (allow-none): the parent of @obj or %NULL
- * @offset: the offset of the range
- * @length: the length of the range
- * @buffer: (out): a memory location to hold the result buffer
- *
- * This function will be called by gst_type_find_helper_get_range() when
- * typefinding functions request to peek at the data of a stream at certain
- * offsets. If this function returns GST_FLOW_OK, the result buffer will be
- * stored in @buffer. The contents of @buffer is invalid for any other
- * return value.
- *
- * This function is supposed to behave exactly like a #GstPadGetRangeFunction.
- *
- * Returns: GST_FLOW_OK for success
- */
-typedef GstFlowReturn (*GstTypeFindHelperGetRangeFunction) (GstObject *obj,
- GstObject *parent,
- guint64 offset,
- guint length,
- GstBuffer **buffer);
-GST_BASE_API
-GstCaps * gst_type_find_helper_get_range (GstObject *obj,
- GstObject *parent,
- GstTypeFindHelperGetRangeFunction func,
- guint64 size,
- const gchar *extension,
- GstTypeFindProbability *prob);
-
-GST_BASE_API
-GstFlowReturn gst_type_find_helper_get_range_full (GstObject *obj,
- GstObject *parent,
- GstTypeFindHelperGetRangeFunction func,
- guint64 size,
- const gchar *extension,
- GstCaps **caps,
- GstTypeFindProbability *prob);
-
-G_END_DECLS
-
-#endif /* __GST_TYPEFINDHELPER_H__ */
diff --git a/libs/gst/base/meson.build b/libs/gst/base/meson.build
deleted file mode 100644
index d289376133..0000000000
--- a/libs/gst/base/meson.build
+++ /dev/null
@@ -1,107 +0,0 @@
-gst_base_sources = [
- 'gstadapter.c',
- 'gstaggregator.c',
- 'gstbaseparse.c',
- 'gstbasesink.c',
- 'gstbasesrc.c',
- 'gstbasetransform.c',
- 'gstbitreader.c',
- 'gstbitwriter.c',
- 'gstbytereader.c',
- 'gstbytewriter.c',
- 'gstcollectpads.c',
- 'gstdataqueue.c',
- 'gstflowcombiner.c',
- 'gstpushsrc.c',
- 'gstqueuearray.c',
- 'gsttypefindhelper.c',
-]
-
-gst_base_headers = [
- 'base.h',
- 'base-prelude.h',
- 'gstadapter.h',
- 'gstaggregator.h',
- 'gstbaseparse.h',
- 'gstbasesink.h',
- 'gstbasesrc.h',
- 'gstbasetransform.h',
- 'gstbitreader.h',
- 'gstbitwriter.h',
- 'gstbytereader.h',
- 'gstbytewriter.h',
- 'gstcollectpads.h',
- 'gstdataqueue.h',
- 'gstflowcombiner.h',
- 'gstpushsrc.h',
- 'gstqueuearray.h',
- 'gsttypefindhelper.h',
-]
-
-gst_base_gen_sources = []
-
-gst_base = library('gstbase-@0@'.format(apiversion),
- gst_base_sources,
- c_args : gst_c_args + ['-DBUILDING_GST_BASE'],
- version : libversion,
- soversion : soversion,
- darwin_versions : osxversion,
- install : true,
- include_directories : [configinc, libsinc],
- dependencies : [gobject_dep, glib_dep, gst_dep],
-)
-
-pkgconfig.generate(gst_base,
- libraries : [libgst],
- variables : pkgconfig_variables,
- subdirs : pkgconfig_subdirs,
- name : 'gstreamer-base-1.0',
- description : 'Base classes for GStreamer elements',
-)
-
-if build_gir
- gst_gir_extra_args = gir_init_section + [ '--c-include=gst/base/base.h' ]
- gst_base_gir = gnome.generate_gir(gst_base,
- sources : gst_base_sources + gst_base_headers,
- namespace : 'GstBase',
- nsversion : apiversion,
- identifier_prefix : 'Gst',
- symbol_prefix : 'gst',
- export_packages : 'gstreamer-base-1.0',
- dependencies : [gst_dep],
- include_directories : [configinc, libsinc, privinc],
- includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
- install : true,
- extra_args : gst_gir_extra_args,
- )
-
- gst_base_gen_sources += [gst_base_gir]
-endif
-
-gst_base_dep = declare_dependency(link_with : gst_base,
- include_directories : [libsinc],
- dependencies : [gst_dep],
- sources : gst_base_gen_sources)
-
-meson.override_dependency('gstreamer-base-1.0', gst_base_dep)
-
-install_headers('base.h',
- 'base-prelude.h',
- 'gstadapter.h',
- 'gstaggregator.h',
- 'gstbaseparse.h',
- 'gstbasesink.h',
- 'gstbasesrc.h',
- 'gstbasetransform.h',
- 'gstbitreader.h',
- 'gstbitwriter.h',
- 'gstbytereader.h',
- 'gstbytewriter.h',
- 'gstcollectpads.h',
- 'gstdataqueue.h',
- 'gstflowcombiner.h',
- 'gstpushsrc.h',
- 'gstqueuearray.h',
- 'gsttypefindhelper.h',
- subdir : 'gstreamer-1.0/gst/base',
-)
diff --git a/libs/gst/check/check-prelude.h b/libs/gst/check/check-prelude.h
deleted file mode 100644
index 0fc272598b..0000000000
--- a/libs/gst/check/check-prelude.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* GStreamer Check Library
- * Copyright (C) 2018 GStreamer developers
- *
- * check-prelude.h: prelude include header for gst-check library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CHECK_PRELUDE_H__
-#define __GST_CHECK_PRELUDE_H__
-
-#include <gst/gst.h>
-
-#ifndef GST_CHECK_API
-#ifdef BUILDING_GST_CHECK
-#define GST_CHECK_API GST_API_EXPORT /* from config.h */
-#else
-#define GST_CHECK_API GST_API_IMPORT
-#endif
-#endif
-
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_CHECK_DEPRECATED GST_CHECK_API
-#define GST_CHECK_DEPRECATED_FOR(f) GST_CHECK_API
-#else
-#define GST_CHECK_DEPRECATED G_DEPRECATED GST_CHECK_API
-#define GST_CHECK_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) GST_CHECK_API
-#endif
-
-#endif /* __GST_CHECK_PRELUDE_H__ */
diff --git a/libs/gst/check/check.h b/libs/gst/check/check.h
deleted file mode 100644
index 512f06ca54..0000000000
--- a/libs/gst/check/check.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* GStreamer
- * Copyright (C) 2012 GStreamer developers
- *
- * check.h: single include header for gst-check library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CHECK__H__
-#define __GST_CHECK__H__
-
-#include <gst/check/check-prelude.h>
-
-#include <gst/check/gstbufferstraw.h>
-#include <gst/check/gstcheck.h>
-#include <gst/check/gstconsistencychecker.h>
-#include <gst/check/gstharness.h>
-#include <gst/check/gsttestclock.h>
-
-#endif /* __GST_CHECK__H__ */
diff --git a/libs/gst/check/gstbufferstraw.c b/libs/gst/check/gstbufferstraw.c
deleted file mode 100644
index 893ae6a4f1..0000000000
--- a/libs/gst/check/gstbufferstraw.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* GStreamer
- *
- * unit testing helper lib
- *
- * Copyright (C) 2006 Andy Wingo <wingo at 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstcheckbufferstraw
- * @title: GstBufferStraw
- * @short_description: Buffer interception 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.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstbufferstraw.h"
-
-static GCond cond;
-static GMutex lock;
-static GstBuffer *buf = NULL;
-static gulong id;
-
-/* called for every buffer. Waits until the global "buf" variable is unset,
- * then sets it to the buffer received, and signals. */
-static GstPadProbeReturn
-buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer unused)
-{
- GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
-
- g_mutex_lock (&lock);
-
- while (buf != NULL)
- g_cond_wait (&cond, &lock);
-
- /* increase the refcount because we store it globally for others to use */
- buf = gst_buffer_ref (buffer);
-
- g_cond_signal (&cond);
-
- g_mutex_unlock (&lock);
-
- return GST_PAD_PROBE_OK;
-}
-
-/**
- * gst_buffer_straw_start_pipeline:
- * @bin: the pipeline to run
- * @pad: a pad on an element in @bin
- *
- * Sets up a pipeline for buffer sucking. This will allow you to call
- * gst_buffer_straw_get_buffer() to access buffers as they pass over @pad.
- *
- * This function is normally used in unit tests that want to verify that a
- * particular element is outputting correct buffers. For example, you would make
- * a pipeline via gst_parse_launch(), pull out the pad you want to monitor, then
- * call gst_buffer_straw_get_buffer() to get the buffers that pass through @pad.
- * The pipeline will block until you have sucked off the buffers.
- *
- * This function will set the state of @bin to PLAYING; to clean up, be sure to
- * call gst_buffer_straw_stop_pipeline().
- *
- * Note that you may not start two buffer straws at the same time. This function
- * is intended for unit tests, not general API use. In fact it calls fail_if
- * from libcheck, so you cannot use it outside unit tests.
- */
-void
-gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad)
-{
- GstStateChangeReturn ret;
-
- id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
- buffer_probe, NULL, NULL);
-
- ret = gst_element_set_state (bin, GST_STATE_PLAYING);
- fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not start test pipeline");
- if (ret == GST_STATE_CHANGE_ASYNC) {
- ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
- fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
- }
-}
-
-/**
- * gst_buffer_straw_get_buffer:
- * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
- * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
- *
- * Get one buffer from @pad. Implemented via buffer probes. This function will
- * block until the pipeline passes a buffer over @pad, so for robust behavior
- * in unit tests, you need to use check's timeout to fail out in the case that a
- * buffer never arrives.
- *
- * You must have previously called gst_buffer_straw_start_pipeline() on
- * @pipeline and @pad.
- *
- * Returns: the captured #GstBuffer.
- */
-GstBuffer *
-gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad)
-{
- GstBuffer *ret;
-
- g_mutex_lock (&lock);
-
- while (buf == NULL)
- g_cond_wait (&cond, &lock);
-
- ret = buf;
- buf = NULL;
-
- g_cond_signal (&cond);
-
- g_mutex_unlock (&lock);
-
- return ret;
-}
-
-/**
- * gst_buffer_straw_stop_pipeline:
- * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
- * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
- *
- * Set @bin to #GST_STATE_NULL and release resource allocated in
- * gst_buffer_straw_start_pipeline().
- *
- * You must have previously called gst_buffer_straw_start_pipeline() on
- * @pipeline and @pad.
- */
-void
-gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad)
-{
- GstStateChangeReturn ret;
-
- g_mutex_lock (&lock);
- if (buf)
- gst_buffer_unref (buf);
- buf = NULL;
- gst_pad_remove_probe (pad, (guint) id);
- id = 0;
- g_cond_signal (&cond);
- g_mutex_unlock (&lock);
-
- ret = gst_element_set_state (bin, GST_STATE_NULL);
- fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not stop test pipeline");
- if (ret == GST_STATE_CHANGE_ASYNC) {
- ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
- fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not stop test pipeline");
- }
-
- g_mutex_lock (&lock);
- if (buf)
- gst_buffer_unref (buf);
- buf = NULL;
- g_mutex_unlock (&lock);
-}
diff --git a/libs/gst/check/gstbufferstraw.h b/libs/gst/check/gstbufferstraw.h
deleted file mode 100644
index 9eec1f9bd4..0000000000
--- a/libs/gst/check/gstbufferstraw.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2006 Andy Wingo <wingo at 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_BUFFER_STRAW_H__
-#define __GST_BUFFER_STRAW_H__
-
-
-#include <gst/check/gstcheck.h>
-
-G_BEGIN_DECLS
-
-GST_CHECK_API
-void gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad);
-
-GST_CHECK_API
-GstBuffer * gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad);
-
-GST_CHECK_API
-void gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad);
-
-G_END_DECLS
-
-#endif /* __GST_BUFFER_STRAW_H__ */
diff --git a/libs/gst/check/gstcheck.c b/libs/gst/check/gstcheck.c
deleted file mode 100644
index 68b4cd3df2..0000000000
--- a/libs/gst/check/gstcheck.c
+++ /dev/null
@@ -1,1306 +0,0 @@
-/* GStreamer
- *
- * Common code for GStreamer unittests
- *
- * Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2008 Thijs Vermeir <thijsvermeir@gmail.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstcheck
- * @title: 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.
- *
- * One notable feature is that one can use the environment variables GST_CHECKS
- * and GST_CHECKS_IGNORE to select which tests to run or skip. Both variables
- * can contain a comma separated list of test name globs (e.g. test_*).
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#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 */
-
-GList *buffers = NULL;
-GMutex check_mutex;
-GCond check_cond;
-
-/* FIXME 2.0: shouldn't _gst_check_debug be static? Not used anywhere */
-gboolean _gst_check_debug = FALSE;
-gboolean _gst_check_raised_critical = FALSE;
-gboolean _gst_check_raised_warning = FALSE;
-gboolean _gst_check_expecting_log = FALSE;
-gboolean _gst_check_list_tests = FALSE;
-static GQueue _gst_check_log_filters = G_QUEUE_INIT;
-static GMutex _gst_check_log_filters_mutex;
-
-struct _GstCheckLogFilter
-{
- gchar *log_domain;
- GLogLevelFlags log_level;
- GRegex *regex;
- GstCheckLogFilterFunc func;
- gpointer user_data;
- GDestroyNotify destroy;
-};
-
-
-static gboolean
-gst_check_match_log_filter (const GstCheckLogFilter * filter,
- const gchar * log_domain, GLogLevelFlags log_level, const gchar * message)
-{
- if (g_strcmp0 (log_domain, filter->log_domain) != 0)
- return FALSE;
-
- if ((log_level & filter->log_level) == 0)
- return FALSE;
-
- if (!g_regex_match (filter->regex, message, 0, NULL))
- return FALSE;
-
- return TRUE;
-}
-
-static GstCheckLogFilter *
-gst_check_alloc_log_filter (const gchar * log_domain, GLogLevelFlags log_level,
- GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data,
- GDestroyNotify destroy_data)
-{
- GstCheckLogFilter *filter;
-
- filter = g_slice_new (GstCheckLogFilter);
- filter->log_domain = g_strdup (log_domain);
- filter->log_level = log_level;
- filter->regex = regex;
- filter->func = func;
- filter->user_data = user_data;
- filter->destroy = destroy_data;
-
- return filter;
-}
-
-static void
-gst_check_free_log_filter (GstCheckLogFilter * filter)
-{
- if (!filter)
- return;
-
- g_free (filter->log_domain);
- g_regex_unref (filter->regex);
- if (filter->destroy)
- filter->destroy (filter->user_data);
- g_slice_free (GstCheckLogFilter, filter);
-}
-
-
-/**
- * gst_check_add_log_filter: (skip)
- * @log_domain: the log domain of the message
- * @log_level: the log level of the message
- * @regex: (transfer full): a #GRegex to match the message
- * @func: the function to call for matching messages
- * @user_data: the user data to pass to @func
- * @destroy_data: #GDestroyNotify for @user_data
- *
- * Add a callback @func to be called for all log messages that matches
- * @log_domain, @log_level and @regex. If @func is NULL the
- * matching logs will be silently discarded by GstCheck.
- *
- * MT safe.
- *
- * Returns: A filter that can be passed to @gst_check_remove_log_filter.
- *
- * Since: 1.12
- **/
-GstCheckLogFilter *
-gst_check_add_log_filter (const gchar * log_domain, GLogLevelFlags log_level,
- GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data,
- GDestroyNotify destroy_data)
-{
- GstCheckLogFilter *filter;
-
- g_return_val_if_fail (regex != NULL, NULL);
-
- filter = gst_check_alloc_log_filter (log_domain, log_level, regex,
- func, user_data, destroy_data);
- g_mutex_lock (&_gst_check_log_filters_mutex);
- g_queue_push_tail (&_gst_check_log_filters, filter);
- g_mutex_unlock (&_gst_check_log_filters_mutex);
-
- return filter;
-}
-
-/**
- * gst_check_remove_log_filter:
- * @filter: Filter returned by @gst_check_add_log_filter
- *
- * Remove a filter that has been added by @gst_check_add_log_filter.
- *
- * MT safe.
- *
- * Since: 1.12
- **/
-void
-gst_check_remove_log_filter (GstCheckLogFilter * filter)
-{
- g_mutex_lock (&_gst_check_log_filters_mutex);
- g_queue_remove (&_gst_check_log_filters, filter);
- gst_check_free_log_filter (filter);
- g_mutex_unlock (&_gst_check_log_filters_mutex);
-}
-
-/**
- * gst_check_clear_log_filter:
- *
- * Clear all filters added by @gst_check_add_log_filter.
- *
- * MT safe.
- *
- * Since: 1.12
- **/
-void
-gst_check_clear_log_filter (void)
-{
- g_mutex_lock (&_gst_check_log_filters_mutex);
- g_queue_foreach (&_gst_check_log_filters,
- (GFunc) gst_check_free_log_filter, NULL);
- g_queue_clear (&_gst_check_log_filters);
- g_mutex_unlock (&_gst_check_log_filters_mutex);
-}
-
-typedef struct
-{
- const gchar *domain;
- const gchar *message;
- GLogLevelFlags level;
- gboolean discard;
-} LogFilterApplyData;
-
-static void
-gst_check_apply_log_filter (GstCheckLogFilter * filter,
- LogFilterApplyData * data)
-{
- if (gst_check_match_log_filter (filter, data->domain, data->level,
- data->message)) {
- if (filter->func)
- data->discard |= filter->func (data->domain, data->level,
- data->message, filter->user_data);
- else
- data->discard = TRUE;
- }
-}
-
-static gboolean
-gst_check_filter_log_filter (const gchar * log_domain,
- GLogLevelFlags log_level, const gchar * message)
-{
- LogFilterApplyData data;
-
- data.domain = log_domain;
- data.level = log_level;
- data.message = message;
- data.discard = FALSE;
-
- g_mutex_lock (&_gst_check_log_filters_mutex);
- g_queue_foreach (&_gst_check_log_filters, (GFunc) gst_check_apply_log_filter,
- &data);
- g_mutex_unlock (&_gst_check_log_filters_mutex);
-
- if (data.discard)
- GST_DEBUG ("Discarding message: %s", message);
-
- return data.discard;
-}
-
-static gboolean
-gst_check_log_fatal_func (const gchar * log_domain, GLogLevelFlags log_level,
- const gchar * message, gpointer user_data)
-{
- if (gst_check_filter_log_filter (log_domain, log_level, message))
- return FALSE;
-
- return TRUE;
-}
-
-
-static void gst_check_log_message_func
- (const gchar * log_domain, GLogLevelFlags log_level,
- const gchar * message, gpointer user_data)
-{
- if (gst_check_filter_log_filter (log_domain, log_level, message))
- return;
-
- if (_gst_check_debug) {
- g_print ("%s\n", message);
- }
-}
-
-static void gst_check_log_critical_func
- (const gchar * log_domain, GLogLevelFlags log_level,
- const gchar * message, gpointer user_data)
-{
- if (gst_check_filter_log_filter (log_domain, log_level, message))
- return;
-
- if (!_gst_check_expecting_log) {
- gchar *trace;
-
- g_print ("\n\nUnexpected critical/warning: %s\n", message);
-
- trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL);
- if (trace) {
- g_print ("\nStack trace:\n%s\n", trace);
- g_free (trace);
- }
- 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;
-}
-
-static gint
-sort_plugins (GstPlugin * a, GstPlugin * b)
-{
- int ret;
-
- ret = strcmp (gst_plugin_get_source (a), gst_plugin_get_source (b));
- if (ret == 0)
- ret = strcmp (gst_plugin_get_name (a), gst_plugin_get_name (b));
- return ret;
-}
-
-static void
-print_plugins (void)
-{
- GList *plugins, *l;
-
- plugins = gst_registry_get_plugin_list (gst_registry_get ());
- plugins = g_list_sort (plugins, (GCompareFunc) sort_plugins);
- for (l = plugins; l != NULL; l = l->next) {
- GstPlugin *plugin = GST_PLUGIN (l->data);
-
- if (strcmp (gst_plugin_get_source (plugin), "BLACKLIST") != 0) {
- GST_LOG ("%20s@%s", gst_plugin_get_name (plugin),
- GST_STR_NULL (gst_plugin_get_filename (plugin)));
- }
- }
- gst_plugin_list_free (plugins);
-}
-
-static void
-gst_check_deinit (void)
-{
- gst_deinit ();
- gst_check_clear_log_filter ();
-}
-
-/* gst_check_init:
- * @argc: (inout) (allow-none): pointer to application's argc
- * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
- *
- * Initialize GStreamer testing
- *
- * NOTE: Needs to be called before creating the testsuite
- * so that the tests can be listed.
- * */
-void
-gst_check_init (int *argc, char **argv[])
-{
- guint timeout_multiplier = 1;
- GOptionContext *ctx;
- GError *err = NULL;
- GOptionEntry options[] = {
- {"list-tests", 'l', 0, G_OPTION_ARG_NONE, &_gst_check_list_tests,
- "List tests present in the testsuite", NULL},
- {NULL}
- };
-
- ctx = g_option_context_new ("gst-check");
- g_option_context_add_main_entries (ctx, options, NULL);
- g_option_context_add_group (ctx, gst_init_get_option_group ());
-
- if (!g_option_context_parse (ctx, argc, argv, &err)) {
- if (err)
- g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message));
- else
- g_printerr ("Error initializing: Unknown error!\n");
- g_clear_error (&err);
- }
- g_option_context_free (ctx);
-
- GST_DEBUG_CATEGORY_INIT (check_debug, "check", 0, "check regression tests");
-
- if (atexit (gst_check_deinit) != 0) {
- GST_ERROR ("failed to set gst_check_deinit as exit function");
- }
-
- 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);
- g_log_set_handler ("GLib-GIO", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
- gst_check_log_critical_func, NULL);
- g_log_set_handler ("GLib", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
- gst_check_log_critical_func, NULL);
- g_test_log_set_fatal_handler (gst_check_log_fatal_func, NULL);
-
- print_plugins ();
-
-#ifdef TARGET_CPU
- GST_INFO ("target CPU: %s", TARGET_CPU);
-#endif
-
-#ifdef HAVE_CPU_ARM
- timeout_multiplier = 10;
-#endif
-
- if (timeout_multiplier > 1) {
- const gchar *tmult = g_getenv ("CK_TIMEOUT_MULTIPLIER");
-
- if (tmult == NULL) {
- gchar num_str[32];
-
- g_snprintf (num_str, sizeof (num_str), "%d", timeout_multiplier);
- GST_INFO ("slow CPU, setting CK_TIMEOUT_MULTIPLIER to %s", num_str);
- g_setenv ("CK_TIMEOUT_MULTIPLIER", num_str, TRUE);
- } else {
- GST_INFO ("CK_TIMEOUT_MULTIPLIER already set to '%s'", tmult);
- }
- }
-}
-
-/* message checking */
-void
-gst_check_message_error (GstMessage * message, GstMessageType type,
- GQuark domain, gint code)
-{
- GError *error;
- gchar *debug;
-
- fail_unless (GST_MESSAGE_TYPE (message) == type,
- "message is of type %s instead of expected type %s",
- gst_message_type_get_name (GST_MESSAGE_TYPE (message)),
- gst_message_type_get_name (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 */
-/**
- * gst_check_chain_func:
- *
- * A fake chain function that appends the buffer to the internal list of
- * buffers.
- */
-GstFlowReturn
-gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer)
-{
- GST_DEBUG_OBJECT (pad, "chain_func: received buffer %p", buffer);
- buffers = g_list_append (buffers, buffer);
-
- g_mutex_lock (&check_mutex);
- g_cond_signal (&check_cond);
- g_mutex_unlock (&check_mutex);
-
- return GST_FLOW_OK;
-}
-
-/**
- * gst_check_setup_element:
- * @factory: factory
- *
- * setup an element for a filter test with mysrcpad and mysinkpad
- *
- * Returns: (transfer full): a new element
- */
-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' element", 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);
-}
-
-/**
- * gst_check_setup_src_pad:
- * @element: element to setup pad on
- * @tmpl: pad template
- *
- * Does the same as #gst_check_setup_src_pad_by_name with the <emphasis> name </emphasis> parameter equal to "sink".
- *
- * Returns: (transfer full): A new pad that can be used to inject data on @element
- */
-GstPad *
-gst_check_setup_src_pad (GstElement * element, GstStaticPadTemplate * tmpl)
-{
- return gst_check_setup_src_pad_by_name (element, tmpl, "sink");
-}
-
-/**
- * gst_check_setup_src_pad_by_name:
- * @element: element to setup src pad on
- * @tmpl: pad template
- * @name: Name of the @element sink pad that will be linked to the src pad that will be setup
- *
- * Creates a new src pad (based on the given @tmpl) and links it to the given @element sink pad (the pad that matches the given @name).
- * Before using the src pad to push data on @element you need to call #gst_check_setup_events on the created src pad.
- *
- * Example of how to push a buffer on @element:
- *
- * |[<!-- language="C" -->
- * static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
- * GST_PAD_SINK,
- * GST_PAD_ALWAYS,
- * GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING)
- * );
- * static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
- * GST_PAD_SRC,
- * GST_PAD_ALWAYS,
- * GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING)
- * );
- *
- * GstElement * element = gst_check_setup_element ("element");
- * GstPad * mysrcpad = gst_check_setup_src_pad (element, &srctemplate);
- * GstPad * mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate);
- *
- * gst_pad_set_active (mysrcpad, TRUE);
- * gst_pad_set_active (mysinkpad, TRUE);
- * fail_unless (gst_element_set_state (element, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
- *
- * GstCaps * caps = gst_caps_from_string (YOUR_DESIRED_SINK_CAPS);
- * gst_check_setup_events (mysrcpad, element, caps, GST_FORMAT_TIME);
- * gst_caps_unref (caps);
- *
- * fail_unless (gst_pad_push (mysrcpad, gst_buffer_new_and_alloc(2)) == GST_FLOW_OK);
- * ]|
- *
- * For very simple input/output test scenarios checkout #gst_check_element_push_buffer_list and #gst_check_element_push_buffer.
- *
- * Returns: (transfer full): A new pad that can be used to inject data on @element
- */
-GstPad *
-gst_check_setup_src_pad_by_name (GstElement * element,
- GstStaticPadTemplate * tmpl, const gchar * name)
-{
- GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl);
- GstPad *srcpad;
-
- srcpad = gst_check_setup_src_pad_by_name_from_template (element, ptmpl, name);
-
- gst_object_unref (ptmpl);
-
- return srcpad;
-}
-
-/**
- * gst_check_setup_src_pad_from_template:
- * @element: element to setup pad on
- * @tmpl: pad template
- *
- * Returns: (transfer full): a new pad
- *
- * Since: 1.4
- */
-GstPad *
-gst_check_setup_src_pad_from_template (GstElement * element,
- GstPadTemplate * tmpl)
-{
- return gst_check_setup_src_pad_by_name_from_template (element, tmpl, "sink");
-}
-
-/**
- * gst_check_setup_src_pad_by_name_from_template:
- * @element: element to setup pad on
- * @tmpl: pad template
- * @name: name
- *
- * Returns: (transfer full): a new pad
- *
- * Since: 1.4
- */
-GstPad *
-gst_check_setup_src_pad_by_name_from_template (GstElement * element,
- GstPadTemplate * tmpl, const gchar * name)
-{
- GstPad *srcpad, *sinkpad;
-
- /* sending pad */
- srcpad = gst_pad_new_from_template (tmpl, "src");
- GST_DEBUG_OBJECT (element, "setting up sending pad %p", srcpad);
- fail_if (srcpad == NULL, "Could not create a srcpad");
- ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
-
- sinkpad = gst_element_get_static_pad (element, name);
- if (sinkpad == NULL)
- sinkpad = gst_element_request_pad_simple (element, name);
- fail_if (sinkpad == NULL, "Could not get sink pad from %s",
- GST_ELEMENT_NAME (element));
- 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 */
-
- return srcpad;
-}
-
-void
-gst_check_teardown_pad_by_name (GstElement * element, const gchar * name)
-{
- GstPad *pad_peer, *pad_element;
-
- /* clean up floating src pad */
- pad_element = gst_element_get_static_pad (element, name);
- /* We don't check the refcount here since there *might* be
- * a pad cache holding an extra reference on pad_element.
- * To get to a state where no pad cache will exist,
- * we first unlink that pad. */
- pad_peer = gst_pad_get_peer (pad_element);
-
- if (pad_peer) {
- if (gst_pad_get_direction (pad_element) == GST_PAD_SINK)
- gst_pad_unlink (pad_peer, pad_element);
- else
- gst_pad_unlink (pad_element, pad_peer);
- }
-
- gst_object_unref (pad_element);
-
- if (pad_peer) {
- gst_object_unref (pad_peer);
- gst_object_unref (pad_peer);
- }
-}
-
-void
-gst_check_teardown_src_pad (GstElement * element)
-{
- gst_check_teardown_pad_by_name (element, "sink");
-}
-
-/**
- * gst_check_setup_sink_pad:
- * @element: element to setup pad on
- * @tmpl: pad template
- *
- * Does the same as #gst_check_setup_sink_pad_by_name with the <emphasis> name </emphasis> parameter equal to "src".
- *
- * Returns: (transfer full): a new pad that can be used to check the output of @element
- */
-GstPad *
-gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl)
-{
- return gst_check_setup_sink_pad_by_name (element, tmpl, "src");
-}
-
-/**
- * gst_check_setup_sink_pad_by_name:
- * @element: element to setup pad on
- * @tmpl: pad template
- * @name: Name of the @element src pad that will be linked to the sink pad that will be setup
- *
- * Creates a new sink pad (based on the given @tmpl) and links it to the given @element src pad
- * (the pad that matches the given @name).
- * You can set event/chain/query functions on this pad to check the output of the @element.
- *
- * Returns: (transfer full): a new pad that can be used to check the output of @element
- */
-GstPad *
-gst_check_setup_sink_pad_by_name (GstElement * element,
- GstStaticPadTemplate * tmpl, const gchar * name)
-{
- GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl);
- GstPad *sinkpad;
-
- sinkpad =
- gst_check_setup_sink_pad_by_name_from_template (element, ptmpl, name);
-
- gst_object_unref (ptmpl);
-
- return sinkpad;
-}
-
-/**
- * gst_check_setup_sink_pad_from_template:
- * @element: element to setup pad on
- * @tmpl: pad template
- *
- * Returns: (transfer full): a new pad
- *
- * Since: 1.4
- */
-GstPad *
-gst_check_setup_sink_pad_from_template (GstElement * element,
- GstPadTemplate * tmpl)
-{
- return gst_check_setup_sink_pad_by_name_from_template (element, tmpl, "src");
-}
-
-/**
- * gst_check_setup_sink_pad_by_name_from_template:
- * @element: element to setup pad on
- * @tmpl: pad template
- * @name: name
- *
- * Returns: (transfer full): a new pad
- *
- * Since: 1.4
- */
-GstPad *
-gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
- GstPadTemplate * tmpl, const gchar * name)
-{
- GstPad *srcpad, *sinkpad;
-
- /* receiving pad */
- sinkpad = gst_pad_new_from_template (tmpl, "sink");
- GST_DEBUG_OBJECT (element, "setting up receiving pad %p", sinkpad);
- fail_if (sinkpad == NULL, "Could not create a sinkpad");
-
- srcpad = gst_element_get_static_pad (element, name);
- if (srcpad == NULL)
- srcpad = gst_element_request_pad_simple (element, name);
- fail_if (srcpad == NULL, "Could not get source pad from %s",
- GST_ELEMENT_NAME (element));
- gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
-
- GST_DEBUG_OBJECT (element, "Linking element src pad and receiving sink pad");
- 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 */
-
- GST_DEBUG_OBJECT (element, "set up srcpad");
- return sinkpad;
-}
-
-void
-gst_check_teardown_sink_pad (GstElement * element)
-{
- gst_check_teardown_pad_by_name (element, "src");
-}
-
-/**
- * gst_check_drop_buffers:
- *
- * Unref and remove all buffers that are in the global @buffers GList,
- * emptying the list.
- */
-void
-gst_check_drop_buffers (void)
-{
- while (buffers != NULL) {
- gst_buffer_unref (GST_BUFFER (buffers->data));
- buffers = g_list_delete_link (buffers, buffers);
- }
-}
-
-/**
- * gst_check_caps_equal:
- * @caps1: first caps to compare
- * @caps2: second caps to compare
- *
- * Compare two caps with gst_caps_is_equal and fail unless they are
- * equal.
- */
-void
-gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2)
-{
- gchar *name1 = gst_caps_to_string (caps1);
- gchar *name2 = gst_caps_to_string (caps2);
-
- fail_unless (gst_caps_is_equal (caps1, caps2),
- "caps ('%s') is not equal to caps ('%s')", name1, name2);
- g_free (name1);
- g_free (name2);
-}
-
-
-/**
- * gst_check_buffer_data:
- * @buffer: buffer to compare
- * @data: data to compare to
- * @size: size of data to compare
- *
- * Compare the buffer contents with @data and @size.
- */
-void
-gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size)
-{
- GstMapInfo info;
-
- fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ));
- GST_MEMDUMP ("Converted data", info.data, info.size);
- GST_MEMDUMP ("Expected data", data, size);
- if (info.size != size) {
- fail ("buffer sizes not equal: expected %" G_GSIZE_FORMAT " got %"
- G_GSIZE_FORMAT, size, info.size);
- }
- if (memcmp (info.data, data, size) != 0) {
- g_print ("\nConverted data:\n");
- gst_util_dump_mem (info.data, info.size);
- g_print ("\nExpected data:\n");
- gst_util_dump_mem (data, size);
- fail ("buffer contents not equal");
- }
- gst_buffer_unmap (buffer, &info);
-}
-
-static gboolean
-buffer_event_function (GstPad * pad, GstObject * noparent, GstEvent * event)
-{
- if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
- GstCaps *event_caps;
- GstCaps *expected_caps = gst_pad_get_element_private (pad);
-
- gst_event_parse_caps (event, &event_caps);
- fail_unless (gst_caps_is_fixed (expected_caps));
- fail_unless (gst_caps_is_fixed (event_caps));
- fail_unless (gst_caps_is_equal_fixed (event_caps, expected_caps));
- gst_event_unref (event);
- return TRUE;
- }
-
- return gst_pad_event_default (pad, noparent, event);
-}
-
-/**
- * gst_check_element_push_buffer_list:
- * @element_name: name of the element that needs to be created
- * @buffer_in: (element-type GstBuffer) (transfer full): a list of buffers that needs to be
- * pushed to the element
- * @caps_in: the #GstCaps expected of the sinkpad of the element
- * @buffer_out: (element-type GstBuffer) (transfer full): a list of buffers that we expect from
- * the element
- * @caps_out: the #GstCaps expected of the srcpad of the element
- * @last_flow_return: the last buffer push needs to give this GstFlowReturn
- *
- * Create an element using the factory providing the @element_name and push the
- * buffers in @buffer_in to this element. The element should create the buffers
- * equal to the buffers in @buffer_out. We only check the size and the data of
- * the buffers. This function unrefs the buffers in the two lists.
- * The last_flow_return parameter indicates the expected flow return value from
- * pushing the final buffer in the list.
- * This can be used to set up a test which pushes some buffers and then an
- * invalid buffer, when the final buffer is expected to fail, for example.
- */
-/* FIXME 2.0: rename this function now that there's GstBufferList? */
-void
-gst_check_element_push_buffer_list (const gchar * element_name,
- GList * buffer_in, GstCaps * caps_in, GList * buffer_out,
- GstCaps * caps_out, GstFlowReturn last_flow_return)
-{
- GstElement *element;
- GstPad *pad_peer;
- GstPad *sink_pad = NULL;
- GstPad *src_pad;
- GstBuffer *buffer;
-
- /* check that there are no buffers waiting */
- gst_check_drop_buffers ();
- /* create the element */
- element = gst_check_setup_element (element_name);
- fail_if (element == NULL, "failed to create the element '%s'", element_name);
- fail_unless (GST_IS_ELEMENT (element), "the element is no element");
- /* create the src pad */
- buffer = GST_BUFFER (buffer_in->data);
-
- fail_unless (GST_IS_BUFFER (buffer), "There should be a buffer in buffer_in");
- src_pad = gst_pad_new ("src", GST_PAD_SRC);
- if (caps_in) {
- fail_unless (gst_caps_is_fixed (caps_in));
- gst_pad_use_fixed_caps (src_pad);
- }
- /* activate the pad */
- gst_pad_set_active (src_pad, TRUE);
- GST_DEBUG ("src pad activated");
- gst_check_setup_events (src_pad, element, caps_in, GST_FORMAT_BYTES);
- pad_peer = gst_element_get_static_pad (element, "sink");
- fail_if (pad_peer == NULL);
- fail_unless (gst_pad_link (src_pad, pad_peer) == GST_PAD_LINK_OK,
- "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
- gst_object_unref (pad_peer);
- /* don't create the sink_pad if there is no buffer_out list */
- if (buffer_out != NULL) {
-
- GST_DEBUG ("buffer out detected, creating the sink pad");
- /* get the sink caps */
- if (caps_out) {
- gchar *temp;
-
- fail_unless (gst_caps_is_fixed (caps_out));
- temp = gst_caps_to_string (caps_out);
-
- GST_DEBUG ("sink caps requested by buffer out: '%s'", temp);
- g_free (temp);
- }
-
- /* get the sink pad */
- sink_pad = gst_pad_new ("sink", GST_PAD_SINK);
- fail_unless (GST_IS_PAD (sink_pad));
- /* configure the sink pad */
- gst_pad_set_chain_function (sink_pad, gst_check_chain_func);
- gst_pad_set_active (sink_pad, TRUE);
- if (caps_out) {
- gst_pad_set_element_private (sink_pad, caps_out);
- gst_pad_set_event_function (sink_pad, buffer_event_function);
- }
- /* get the peer pad */
- pad_peer = gst_element_get_static_pad (element, "src");
- fail_unless (gst_pad_link (pad_peer, sink_pad) == GST_PAD_LINK_OK,
- "Could not link sink and %s source pads", GST_ELEMENT_NAME (element));
- gst_object_unref (pad_peer);
- }
- fail_unless (gst_element_set_state (element,
- GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
- "could not set to playing");
- /* push all the buffers in the buffer_in list */
- fail_unless (g_list_length (buffer_in) > 0, "the buffer_in list is empty");
- while (buffer_in != NULL) {
- GstBuffer *next_buffer = GST_BUFFER (buffer_in->data);
-
- fail_unless (GST_IS_BUFFER (next_buffer),
- "data in buffer_in should be a buffer");
- /* remove the buffer from the list */
- buffer_in = g_list_remove (buffer_in, next_buffer);
- if (buffer_in == NULL) {
- fail_unless (gst_pad_push (src_pad, next_buffer) == last_flow_return,
- "we expect something else from the last buffer");
- } else {
- fail_unless (gst_pad_push (src_pad, next_buffer) == GST_FLOW_OK,
- "Failed to push buffer in");
- }
- }
- fail_unless (gst_element_set_state (element,
- GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
- /* check that there is a buffer out */
- fail_unless_equals_int (g_list_length (buffers), g_list_length (buffer_out));
- while (buffers != NULL) {
- GstBuffer *new = GST_BUFFER (buffers->data);
- GstBuffer *orig = GST_BUFFER (buffer_out->data);
- GstMapInfo newinfo, originfo;
-
- fail_unless (gst_buffer_map (new, &newinfo, GST_MAP_READ));
- fail_unless (gst_buffer_map (orig, &originfo, GST_MAP_READ));
-
- GST_LOG ("orig buffer: size %" G_GSIZE_FORMAT, originfo.size);
- GST_LOG ("new buffer: size %" G_GSIZE_FORMAT, newinfo.size);
- GST_MEMDUMP ("orig buffer", originfo.data, originfo.size);
- GST_MEMDUMP ("new buffer", newinfo.data, newinfo.size);
-
- /* remove the buffers */
- buffers = g_list_remove (buffers, new);
- buffer_out = g_list_remove (buffer_out, orig);
-
- fail_unless (originfo.size == newinfo.size,
- "size of the buffers are not the same");
- fail_unless (memcmp (originfo.data, newinfo.data, newinfo.size) == 0,
- "data is not the same");
-#if 0
- gst_check_caps_equal (GST_BUFFER_CAPS (orig), GST_BUFFER_CAPS (new));
-#endif
-
- gst_buffer_unmap (orig, &originfo);
- gst_buffer_unmap (new, &newinfo);
-
- gst_buffer_unref (new);
- gst_buffer_unref (orig);
- }
- /* teardown the element and pads */
- gst_pad_set_active (src_pad, FALSE);
- gst_check_teardown_src_pad (element);
- gst_pad_set_active (sink_pad, FALSE);
- gst_check_teardown_sink_pad (element);
- gst_check_teardown_element (element);
-}
-
-/**
- * gst_check_element_push_buffer:
- * @element_name: name of the element that needs to be created
- * @buffer_in: push this buffer to the element
- * @caps_in: the #GstCaps expected of the sinkpad of the element
- * @buffer_out: compare the result with this buffer
- * @caps_out: the #GstCaps expected of the srcpad of the element
- *
- * Create an element using the factory providing the @element_name and
- * push the @buffer_in to this element. The element should create one buffer
- * and this will be compared with @buffer_out. We only check the caps
- * and the data of the buffers. This function unrefs the buffers.
- */
-void
-gst_check_element_push_buffer (const gchar * element_name,
- GstBuffer * buffer_in, GstCaps * caps_in, GstBuffer * buffer_out,
- GstCaps * caps_out)
-{
- GList *in = NULL;
- GList *out = NULL;
-
- in = g_list_append (in, buffer_in);
- out = g_list_append (out, buffer_out);
-
- gst_check_element_push_buffer_list (element_name, in, caps_in, out, caps_out,
- GST_FLOW_OK);
-}
-
-/**
- * gst_check_abi_list:
- * @list: A list of GstCheckABIStruct to be verified
- * @have_abi_sizes: Whether there is a reference ABI size already specified,
- * if it is %FALSE and the `GST_ABI` environment variable is set, usable code
- * for @list will be printed.
- *
- * Verifies that reference values and current values are equals in @list.
- */
-void
-gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes)
-{
- if (have_abi_sizes) {
- gboolean ok = TRUE;
- gint i;
-
- for (i = 0; list[i].name; i++) {
- if (list[i].size != list[i].abi_size) {
- ok = FALSE;
- g_print ("sizeof(%s) is %d, expected %d\n",
- list[i].name, list[i].size, list[i].abi_size);
- }
- }
- fail_unless (ok, "failed ABI check");
- } else {
- const gchar *fn;
-
- if ((fn = g_getenv ("GST_ABI"))) {
- GError *err = NULL;
- GString *s;
- gint i;
-
- s = g_string_new ("\nGstCheckABIStruct list[] = {\n");
- for (i = 0; list[i].name; i++) {
- g_string_append_printf (s, " {\"%s\", sizeof (%s), %d},\n",
- list[i].name, list[i].name, list[i].size);
- }
- g_string_append (s, " {NULL, 0, 0}\n");
- g_string_append (s, "};\n");
- if (!g_file_set_contents (fn, s->str, s->len, &err)) {
- g_print ("%s", s->str);
- g_printerr ("\nFailed to write ABI information: %s\n", err->message);
- g_clear_error (&err);
- } else {
- g_print ("\nWrote ABI information to '%s'.\n", fn);
- }
- g_string_free (s, TRUE);
- } else {
- g_print ("No structure size list was generated for this architecture.\n");
- g_print ("Run with GST_ABI environment variable set to output header.\n");
- }
- }
-}
-
-/**
- * gst_check_run_suite: (skip)
- * @suite: the check test suite
- * @name: name
- * @fname: file name
- *
- * Returns: number of failed tests
- */
-gint
-gst_check_run_suite (Suite * suite, const gchar * name, const gchar * fname)
-{
- SRunner *sr;
- gchar *xmlfilename = NULL;
- gint nf;
- GTimer *timer;
-
- sr = srunner_create (suite);
-
- if (g_getenv ("GST_CHECK_XML")) {
- /* how lucky we are to have __FILE__ end in .c */
- xmlfilename = g_strdup_printf ("%sheck.xml", fname);
-
- srunner_set_xml (sr, xmlfilename);
- }
-
- timer = g_timer_new ();
- srunner_run_all (sr, CK_NORMAL);
- nf = srunner_ntests_failed (sr);
- g_print ("Check suite %s ran in %.3fs (tests failed: %d)\n",
- name, g_timer_elapsed (timer, NULL), nf);
- g_timer_destroy (timer);
- g_free (xmlfilename);
- srunner_free (sr);
- g_thread_pool_stop_unused_threads ();
- return nf;
-}
-
-static gboolean
-gst_check_have_checks_list (const gchar * env_var_name)
-{
- const gchar *env_val;
-
- env_val = g_getenv (env_var_name);
- return (env_val != NULL && *env_val != '\0');
-}
-
-static gboolean
-gst_check_func_is_in_list (const gchar * env_var, const gchar * func_name)
-{
- const gchar *gst_checks;
- gboolean res = FALSE;
- gchar **funcs, **f;
-
- gst_checks = g_getenv (env_var);
-
- if (gst_checks == NULL || *gst_checks == '\0')
- return FALSE;
-
- /* only run specified functions */
- funcs = g_strsplit (gst_checks, ",", -1);
- for (f = funcs; f != NULL && *f != NULL; ++f) {
- if (g_pattern_match_simple (*f, func_name)) {
- res = TRUE;
- break;
- }
- }
- g_strfreev (funcs);
- return res;
-}
-
-gboolean
-_gst_check_run_test_func (const gchar * func_name)
-{
- /* if we have a whitelist, run it only if it's in the whitelist */
- if (gst_check_have_checks_list ("GST_CHECKS"))
- return gst_check_func_is_in_list ("GST_CHECKS", func_name);
-
- /* if we have a blacklist, run it only if it's not in the blacklist */
- if (gst_check_have_checks_list ("GST_CHECKS_IGNORE"))
- return !gst_check_func_is_in_list ("GST_CHECKS_IGNORE", func_name);
-
- /* no filter specified => run all checks */
- return TRUE;
-}
-
-/**
- * gst_check_setup_events_with_stream_id:
- * @srcpad: The src #GstPad to push on
- * @element: The #GstElement use to create the stream id
- * @caps: (allow-none): #GstCaps in case caps event must be sent
- * @format: The #GstFormat of the default segment to send
- * @stream_id: A unique identifier for the stream
- *
- * Push stream-start, caps and segment event, which consist of the minimum
- * required events to allow streaming. Caps is optional to allow raw src
- * testing.
- */
-void
-gst_check_setup_events_with_stream_id (GstPad * srcpad, GstElement * element,
- GstCaps * caps, GstFormat format, const gchar * stream_id)
-{
- GstSegment segment;
-
- gst_segment_init (&segment, format);
-
- fail_unless (gst_pad_push_event (srcpad,
- gst_event_new_stream_start (stream_id)));
- if (caps)
- fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
- fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
-}
-
-/**
- * gst_check_setup_events:
- * @srcpad: The src #GstPad to push on
- * @element: The #GstElement use to create the stream id
- * @caps: (allow-none): #GstCaps in case caps event must be sent
- * @format: The #GstFormat of the default segment to send
- *
- * Push stream-start, caps and segment event, which consist of the minimum
- * required events to allow streaming. Caps is optional to allow raw src
- * testing. If @element has more than one src or sink pad, use
- * gst_check_setup_events_with_stream_id() instead.
- */
-void
-gst_check_setup_events (GstPad * srcpad, GstElement * element,
- GstCaps * caps, GstFormat format)
-{
- gchar *stream_id;
-
- stream_id = gst_pad_create_stream_id (srcpad, element, NULL);
- gst_check_setup_events_with_stream_id (srcpad, element, caps, format,
- stream_id);
- g_free (stream_id);
-}
-
-typedef struct _DestroyedObjectStruct
-{
- GObject *object;
- gboolean destroyed;
-} DestroyedObjectStruct;
-
-static void
-weak_notify (DestroyedObjectStruct * destroyed, GObject ** object)
-{
- destroyed->destroyed = TRUE;
-}
-
-/**
- * gst_check_objects_destroyed_on_unref:
- * @object_to_unref: The #GObject to unref
- * @first_object: (allow-none): The first object that should be destroyed as a
- * concequence of unrefing @object_to_unref.
- * @... : Additional object that should have been destroyed.
- *
- * Unrefs @object_to_unref and checks that is has properly been
- * destroyed, also checks that the other objects passed in
- * parameter have been destroyed as a concequence of
- * unrefing @object_to_unref. Last variable argument should be NULL.
- *
- * Since: 1.6
- */
-void
-gst_check_objects_destroyed_on_unref (gpointer object_to_unref,
- gpointer first_object, ...)
-{
- GObject *object;
- GList *objs = NULL, *tmp;
- DestroyedObjectStruct *destroyed = g_slice_new0 (DestroyedObjectStruct);
-
- destroyed->object = object_to_unref;
- g_object_weak_ref (object_to_unref, (GWeakNotify) weak_notify, destroyed);
- objs = g_list_prepend (objs, destroyed);
-
- if (first_object) {
- va_list varargs;
-
- object = first_object;
-
- va_start (varargs, first_object);
- while (object) {
- destroyed = g_slice_new0 (DestroyedObjectStruct);
- destroyed->object = object;
- g_object_weak_ref (object, (GWeakNotify) weak_notify, destroyed);
- objs = g_list_prepend (objs, destroyed);
- object = va_arg (varargs, GObject *);
- }
- va_end (varargs);
- }
- gst_object_unref (object_to_unref);
-
- for (tmp = objs; tmp; tmp = tmp->next) {
- DestroyedObjectStruct *destroyed = tmp->data;
-
- if (!destroyed->destroyed) {
- fail_unless (destroyed->destroyed,
- "%s_%p is not destroyed, %d refcounts left!",
- GST_IS_OBJECT (destroyed->
- object) ? GST_OBJECT_NAME (destroyed->object) :
- G_OBJECT_TYPE_NAME (destroyed), destroyed->object,
- destroyed->object->ref_count);
- }
- g_slice_free (DestroyedObjectStruct, tmp->data);
- }
- g_list_free (objs);
-}
-
-/**
- * gst_check_object_destroyed_on_unref:
- * @object_to_unref: The #GObject to unref
- *
- * Unrefs @object_to_unref and checks that is has properly been
- * destroyed.
- *
- * Since: 1.6
- */
-void
-gst_check_object_destroyed_on_unref (gpointer object_to_unref)
-{
- gst_check_objects_destroyed_on_unref (object_to_unref, NULL, NULL);
-}
-
-/* For ABI compatibility with GStreamer < 1.5 */
-/* *INDENT-OFF* */
-GST_CHECK_API void
-_fail_unless (int result, const char *file, int line, const char *expr, ...)
-G_GNUC_PRINTF (4, 5);
-/* *INDENT-ON* */
-
-void
-_fail_unless (int result, const char *file, int line, const char *expr, ...)
-{
- gchar *msg;
- va_list args;
-
- if (result) {
- _mark_point (file, line);
- return;
- }
-
- va_start (args, expr);
- msg = g_strdup_vprintf (expr, args);
- va_end (args);
-
- _ck_assert_failed (file, line, msg, NULL);
- g_free (msg);
-}
diff --git a/libs/gst/check/gstcheck.h b/libs/gst/check/gstcheck.h
deleted file mode 100644
index b7ec2c4ab3..0000000000
--- a/libs/gst/check/gstcheck.h
+++ /dev/null
@@ -1,756 +0,0 @@
-/* GStreamer
- *
- * Common code for GStreamer unittests
- *
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) <2008> Thijs Vermeir <thijsvermeir@gmail.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CHECK_H__
-#define __GST_CHECK_H__
-
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <gst/gst.h>
-#include <gst/check/check-prelude.h>
-
-#define CK_DLL_EXP GST_CHECK_API
-#include <gst/check/internal-check.h>
-
-G_BEGIN_DECLS
-
-GST_CHECK_API GstDebugCategory *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
- */
-GST_CHECK_API gboolean _gst_check_threads_running;
-GST_CHECK_API gboolean _gst_check_raised_critical;
-GST_CHECK_API gboolean _gst_check_raised_warning;
-GST_CHECK_API gboolean _gst_check_expecting_log;
-GST_CHECK_API gboolean _gst_check_list_tests;
-
-/* global variables used in test methods */
-GST_CHECK_API GList * buffers;
-
-GST_CHECK_API GMutex check_mutex;
-GST_CHECK_API GCond check_cond;
-
-/**
- * GstCheckABIStruct:
- * @name: The name of the structure
- * @size: The current size of a structure
- * @abi_size: The reference size of the structure
- */
-typedef struct
-{
- const char *name;
- int size;
- int abi_size;
-}
-GstCheckABIStruct;
-
-/**
- * GstCheckLogFilter:
- *
- * Opaque structure containing data about a log filter
- * function.
- */
-typedef struct _GstCheckLogFilter GstCheckLogFilter;
-
-/**
- * GstCheckLogFilterFunc:
- * @log_domain: the log domain of the message
- * @log_level: the log level of the message
- * @message: the message that has occurred
- * @user_data: user data
- *
- * A function that is called for messages matching the filter added by
- * @gst_check_add_log_filter.
- *
- * Returns: %TRUE if message should be discarded by GstCheck.
- *
- * Since: 1.12
- */
-typedef gboolean (*GstCheckLogFilterFunc) (const gchar * log_domain,
- GLogLevelFlags log_level, const gchar * message, gpointer user_data);
-
-GST_CHECK_API
-void gst_check_init (int *argc, char **argv[]);
-
-GST_CHECK_API
-GstCheckLogFilter * gst_check_add_log_filter (const gchar * log_domain,
- GLogLevelFlags log_level, GRegex * regex, GstCheckLogFilterFunc func,
- gpointer user_data, GDestroyNotify destroy_data);
-
-GST_CHECK_API
-void gst_check_remove_log_filter (GstCheckLogFilter * filter);
-
-GST_CHECK_API
-void gst_check_clear_log_filter (void);
-
-GST_CHECK_API
-GstFlowReturn gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer);
-
-GST_CHECK_API
-void gst_check_message_error (GstMessage * message, GstMessageType type,
- GQuark domain, gint code);
-
-GST_CHECK_API
-GstElement *gst_check_setup_element (const gchar * factory);
-
-GST_CHECK_API
-void gst_check_teardown_element (GstElement * element);
-
-GST_CHECK_API
-GstPad *gst_check_setup_src_pad (GstElement * element,
- GstStaticPadTemplate * tmpl);
-
-GST_CHECK_API
-GstPad *gst_check_setup_src_pad_from_template (GstElement * element,
- GstPadTemplate * tmpl);
-
-GST_CHECK_API
-GstPad * gst_check_setup_src_pad_by_name (GstElement * element,
- GstStaticPadTemplate * tmpl, const gchar *name);
-
-GST_CHECK_API
-GstPad * gst_check_setup_src_pad_by_name_from_template (GstElement * element,
- GstPadTemplate * tmpl, const gchar *name);
-
-GST_CHECK_API
-GstPad *gst_check_setup_sink_pad (GstElement * element,
- GstStaticPadTemplate * tmpl);
-
-GST_CHECK_API
-GstPad *gst_check_setup_sink_pad_from_template (GstElement * element,
- GstPadTemplate * tmpl);
-
-GST_CHECK_API
-GstPad * gst_check_setup_sink_pad_by_name (GstElement * element,
- GstStaticPadTemplate * tmpl, const gchar *name);
-
-GST_CHECK_API
-GstPad * gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
- GstPadTemplate * tmpl, const gchar *name);
-
-GST_CHECK_API
-void gst_check_teardown_pad_by_name (GstElement * element, const gchar *name);
-
-GST_CHECK_API
-void gst_check_teardown_src_pad (GstElement * element);
-
-GST_CHECK_API
-void gst_check_drop_buffers (void);
-
-GST_CHECK_API
-void gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2);
-
-GST_CHECK_API
-void gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size);
-
-GST_CHECK_API
-void gst_check_element_push_buffer_list (const gchar * element_name,
- GList * buffer_in, GstCaps * caps_in, GList * buffer_out,
- GstCaps * caps_out, GstFlowReturn last_flow_return);
-
-GST_CHECK_API
-void gst_check_element_push_buffer (const gchar * element_name,
- GstBuffer * buffer_in, GstCaps * caps_in, GstBuffer * buffer_out,
- GstCaps *caps_out);
-
-GST_CHECK_API
-void gst_check_teardown_sink_pad (GstElement * element);
-
-GST_CHECK_API
-void gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes);
-
-GST_CHECK_API
-gint gst_check_run_suite (Suite * suite, const gchar * name,
- const gchar * fname);
-
-GST_CHECK_API
-void gst_check_setup_events (GstPad * srcpad, GstElement * element,
- GstCaps * caps, GstFormat format);
-
-GST_CHECK_API
-void gst_check_setup_events_with_stream_id (GstPad * srcpad,
- GstElement * element, GstCaps * caps, GstFormat format,
- const gchar * stream_id);
-
-GST_CHECK_API
-void gst_check_objects_destroyed_on_unref (gpointer object_to_unref, gpointer first_object, ...)
- G_GNUC_NULL_TERMINATED;
-
-GST_CHECK_API
-void gst_check_object_destroyed_on_unref (gpointer object_to_unref);
-
-#ifndef __GI_SCANNER__
-
-#define fail_unless_message_error(msg, domain, code) \
-gst_check_message_error (msg, GST_MESSAGE_ERROR, \
- GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code)
-#define assert_message_error(m, d, c) fail_unless_message_error(m, d, c)
-
-#ifdef GST_CHECK_TEST_ENVIRONMENT_BEACON
-#define GST_DO_CHECK_TEST_ENVIRONMENT \
-G_STMT_START { \
- if (g_getenv (GST_CHECK_TEST_ENVIRONMENT_BEACON) == NULL) \
- fail ("Test environment not set up correctly! Expected environment " \
- "variable '%s' to be set.", GST_CHECK_TEST_ENVIRONMENT_BEACON); \
-} G_STMT_END
-
-#else
-#define GST_DO_CHECK_TEST_ENVIRONMENT /* nothing to check */
-#endif
-
-/**
- * GST_START_TEST:
- * @__testname: test function name
- *
- * wrapper for checks START_TEST
- */
-/**
- * GST_END_TEST:
- *
- * wrapper for checks END_TEST
- */
-#define GST_START_TEST(__testname) \
-static void __testname (int G_GNUC_UNUSED __i__) \
-{\
- GST_DEBUG ("test start"); \
- GST_DO_CHECK_TEST_ENVIRONMENT; \
- tcase_fn_start (""# __testname, __FILE__, __LINE__);
-
-#define GST_END_TEST GST_LOG ("cleaning up tasks"); \
- gst_task_cleanup_all (); \
- END_TEST
-
-/* additional fail macros */
-/**
- * fail_unless_equals_int:
- * @a: a #gint value or expression
- * @b: a #gint value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#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;
-/**
- * assert_equals_int:
- * @a: a #gint value or expression
- * @b: a #gint value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#define assert_equals_int(a, b) fail_unless_equals_int(a, b)
-
-/**
- * fail_unless_equals_int_hex:
- * @a: a #gint value or expression
- * @b: a #gint value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define fail_unless_equals_int_hex(a, b) \
-G_STMT_START { \
- int first = a; \
- int second = b; \
- fail_unless(first == second, \
- "'" #a "' (0x%08x) is not equal to '" #b"' (0x%08x)", first, second);\
-} G_STMT_END;
-
-/**
- * assert_equals_int_hex:
- * @a: a #gint value or expression
- * @b: a #gint value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define assert_equals_int_hex(a, b) fail_unless_equals_int_hex(a, b)
-
-/**
- * fail_unless_equals_int64:
- * @a: a #gint64 value or expression
- * @b: a #gint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#define fail_unless_equals_int64(a, b) \
-G_STMT_START { \
- gint64 first = a; \
- gint64 second = b; \
- fail_unless(first == second, \
- "'" #a "' (%" G_GINT64_FORMAT") is not equal to '" #b"' (%" \
- G_GINT64_FORMAT")", first, second); \
-} G_STMT_END;
-/**
- * assert_equals_int64:
- * @a: a #gint64 value or expression
- * @b: a #gint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#define assert_equals_int64(a, b) fail_unless_equals_int64(a, b)
-
-/**
- * fail_unless_equals_int64_hex:
- * @a: a #gint64 value or expression
- * @b: a #gint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define fail_unless_equals_int64_hex(a, b) \
-G_STMT_START { \
- gint64 first = a; \
- gint64 second = b; \
- fail_unless(first == second, \
- "'" #a "' (0x%016x) is not equal to '" #b"' (0x%016x)", first, second);\
-} G_STMT_END;
-/**
- * assert_equals_int64_hex:
- * @a: a #gint64 value or expression
- * @b: a #gint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define assert_equals_int64_hex(a,b) fail_unless_equals_int64_hex(a,b)
-
-/**
- * fail_unless_equals_uint64:
- * @a: a #guint64 value or expression
- * @b: a #guint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#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;
-/**
- * assert_equals_uint64:
- * @a: a #guint64 value or expression
- * @b: a #guint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#define assert_equals_uint64(a, b) fail_unless_equals_uint64(a, b)
-
-/**
- * fail_unless_equals_uint64_hex:
- * @a: a #gint64 value or expression
- * @b: a #gint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define fail_unless_equals_uint64_hex(a, b) \
-G_STMT_START { \
- guint64 first = a; \
- guint64 second = b; \
- fail_unless(first == second, \
- "'" #a "' (0x%016x) is not equal to '" #b"' (0x%016x)", first, second);\
-} G_STMT_END;
-/**
- * assert_equals_uint64_hex:
- * @a: a #guint64 value or expression
- * @b: a #guint64 value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to in
- * hexadecimal format. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define assert_equals_uint64_hex(a,b) fail_unless_equals_uint64_hex(a,b)
-
-/**
- * fail_unless_equals_string:
- * @a: a string literal or expression
- * @b: a string literal or expression
- *
- * This macro checks that @a and @b are equal (as per g_strcmp0()) and aborts if
- * this is not the case, printing both expressions and the values they
- * evaluated to. This macro is for use in unit tests.
- */
-#define fail_unless_equals_string(a, b) \
-G_STMT_START { \
- const gchar * first = a; \
- const gchar * second = b; \
- fail_unless(g_strcmp0 (first, second) == 0, \
- "'" #a "' (%s) is not equal to '" #b"' (%s)", first, second); \
-} G_STMT_END;
-/**
- * assert_equals_string:
- * @a: a string literal or expression
- * @b: a string literal or expression
- *
- * This macro checks that @a and @b are equal (as per g_strcmp0()) and aborts if
- * this is not the case, printing both expressions and the values they
- * evaluated to. This macro is for use in unit tests.
- */
-#define assert_equals_string(a, b) fail_unless_equals_string(a, b)
-
-/**
- * fail_unless_equals_float:
- * @a: a #gdouble or #gfloat value or expression
- * @b: a #gdouble or #gfloat value or expression
- *
- * This macro checks that @a and @b are (almost) equal and aborts if this
- * is not the case, printing both expressions and the values they evaluated
- * to. This macro is for use in unit tests.
- */
-#define fail_unless_equals_float(a, b) \
-G_STMT_START { \
- double first = a; \
- double second = b; \
- /* This will only work for 'normal' values and values around 0, \
- * which should be good enough for our purposes here */ \
- fail_unless(fabs (first - second) < 0.0000001, \
- "'" #a "' (%g) is not equal to '" #b "' (%g)", first, second);\
-} G_STMT_END;
-
-/**
- * assert_equals_float:
- * @a: a #gdouble or #gfloat value or expression
- * @b: a #gdouble or #gfloat value or expression
- *
- * This macro checks that @a and @b are (almost) equal and aborts if this
- * is not the case, printing both expressions and the values they evaluated
- * to. This macro is for use in unit tests.
- */
-#define assert_equals_float(a, b) fail_unless_equals_float(a, b)
-
-/**
- * fail_unless_equals_pointer:
- * @a: a pointer value or expression
- * @b: a pointer value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this
- * is not the case, printing both expressions and the values they
- * evaluated to. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define fail_unless_equals_pointer(a, b) \
-G_STMT_START { \
- gpointer first = a; \
- gpointer second = b; \
- fail_unless(first == second, \
- "'" #a "' (%p) is not equal to '" #b "' (%p)", first, second);\
-} G_STMT_END;
-
-/**
- * assert_equals_pointer:
- * @a: a pointer value or expression
- * @b: a pointer value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this
- * is not the case, printing both expressions and the values they
- * evaluated to. This macro is for use in unit tests.
- *
- * Since: 1.2
- */
-#define assert_equals_pointer(a, b) fail_unless_equals_pointer(a, b)
-
-/**
- * fail_unless_equals_clocktime:
- * @a: a #GstClockTime value or expression
- * @b: a #GstClockTime value or expression
- *
- * This macro checks that @a and @b are equal and aborts if this is not the
- * case, printing both expressions and the values they evaluated to. This
- * macro is for use in unit tests.
- */
-#define fail_unless_equals_clocktime(a, b) \
-G_STMT_START { \
- GstClockTime first = a; \
- GstClockTime second = b; \
- fail_unless(first == second, \
- "'" #a "' (%" GST_TIME_FORMAT") is not equal to '" #b"' (%" GST_TIME_FORMAT")", \
- GST_TIME_ARGS (first), GST_TIME_ARGS (second)); \
-} G_STMT_END;
-
-/***
- * thread test macros and variables
- */
-GST_CHECK_API GList *thread_list;
-GST_CHECK_API GMutex mutex;
-GST_CHECK_API GCond start_cond; /* used to notify main thread of thread startups */
-GST_CHECK_API 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 { \
- g_mutex_init (&mutex); \
- g_cond_init (&start_cond); \
- g_cond_init (&sync_cond); \
- _gst_check_threads_running = TRUE; \
-} 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_try_new ("gst-check", \
- (GThreadFunc) function, data, 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); \
- g_list_free (thread_list); \
- thread_list = NULL; \
- g_mutex_clear (&mutex); \
- g_cond_clear (&start_cond); \
- g_cond_clear (&sync_cond); \
- 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 ()); \
- fail_if (g_mutex_trylock (&mutex), \
- "bug in unit test, mutex should be locked at this point");\
- 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 { \
- g_thread_yield (); \
-} G_STMT_END;
-
-#define THREAD_TEST_RUNNING() (!!_gst_check_threads_running)
-
-/* additional assertions */
-
-#if GST_DISABLE_GLIB_CHECKS
-#define ASSERT_CRITICAL(code)
-#else
-#define ASSERT_CRITICAL(code) \
-G_STMT_START { \
- _gst_check_expecting_log = TRUE; \
- _gst_check_raised_critical = FALSE; \
- code; \
- if (!_gst_check_raised_critical) \
- _ck_assert_failed (__FILE__, __LINE__, \
- "Expected g_critical, got nothing", NULL); \
- _gst_check_expecting_log = FALSE; \
-} G_STMT_END
-#endif /* GST_DISABLE_GLIB_CHECKS */
-
-#define ASSERT_WARNING(code) \
-G_STMT_START { \
- _gst_check_expecting_log = TRUE; \
- _gst_check_raised_warning = FALSE; \
- code; \
- if (!_gst_check_raised_warning) \
- _ck_assert_failed (__FILE__, __LINE__, \
- "Expected g_warning, got nothing", NULL); \
- _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(miniobj, name, value) \
-G_STMT_START { \
- int rc; \
- rc = GST_MINI_OBJECT_REFCOUNT_VALUE (miniobj); \
- fail_unless (rc == value, \
- name " (%p) refcount is %d instead of %d", miniobj, rc, value); \
-} G_STMT_END
-
-#define ASSERT_SET_STATE(element, state, ret) \
-fail_unless (gst_element_set_state (GST_ELEMENT(element), \
- state) == ret, \
- "could not change state to " #state);
-
-#define GST_CHECK_MAIN(name) \
-int main (int argc, char **argv) \
-{ \
- Suite *s; \
- gst_check_init (&argc, &argv); \
- s = name ## _suite (); \
- return gst_check_run_suite (s, # name, __FILE__); \
-}
-
-/* Hack to allow run-time selection of unit tests to run via the
- * GST_CHECKS environment variable (test function names globs, comma
- * separated), or GST_CHECKS_IGNORE with the same semantics */
-
-GST_CHECK_API
-gboolean _gst_check_run_test_func (const gchar * func_name);
-
-static inline void
-__gst_tcase_add_test (TCase * tc, TFun tf, const char * fname, int signal,
- int allowed_exit_value, int start, int end)
-{
- if (_gst_check_list_tests) {
- g_print ("Test: %s\n", fname);
- return;
- }
-
- if (_gst_check_run_test_func (fname)) {
- _tcase_add_test (tc, tf, fname, signal, allowed_exit_value, start, end);
- }
-}
-
-#define _tcase_add_test __gst_tcase_add_test
-
-/* A special variant to add broken tests. These are normally skipped, but can be
- * forced to run via GST_CHECKS */
-#define tcase_skip_broken_test(chain,test_func) \
-G_STMT_START { \
- const char *env = g_getenv ("GST_CHECKS"); \
- \
- if (env != NULL && g_pattern_match_simple (env, G_STRINGIFY (test_func))) { \
- tcase_add_test(chain,test_func); \
- } else { \
- g_printerr ("FIXME: skipping test %s because it's broken\n", G_STRINGIFY (test_func)); \
- } \
-} G_STMT_END
-
-#define tcase_skip_broken_loop_test(chain,test_func,a,b) \
- tcase_skip_broken_test (chain, test_func)
-
-#endif /* !__GI_SCANNER__ */
-
-G_END_DECLS
-
-#endif /* __GST_CHECK_H__ */
diff --git a/libs/gst/check/gstconsistencychecker.c b/libs/gst/check/gstconsistencychecker.c
deleted file mode 100644
index 08f720e89c..0000000000
--- a/libs/gst/check/gstconsistencychecker.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/* GStreamer
- *
- * unit testing helper lib
- *
- * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
- * Copyright (C) 2012 Stefan Sauer <ensonic@users.sf.net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstcheckconsistencychecker
- * @title: GstStreamConsistencyChecker
- * @short_description: Data flow consistency checker 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.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstconsistencychecker.h"
-
-struct _GstStreamConsistency
-{
- /* FIXME: do we want to track some states per pad? */
- gboolean flushing;
- gboolean segment;
- gboolean eos;
- gboolean expect_flush;
- gboolean saw_serialized_event;
- gboolean saw_stream_start;
- GstObject *parent;
- GList *pads;
-};
-
-typedef struct _GstStreamConsistencyProbe
-{
- GstPad *pad;
- gulong probeid;
-} GstStreamConsistencyProbe;
-
-static gboolean
-source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info,
- GstStreamConsistency * consist)
-{
- GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info);
-
- GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing,
- consist->segment, consist->eos, consist->expect_flush);
-
- if (GST_IS_BUFFER (data)) {
- GST_DEBUG_OBJECT (pad,
- "Buffer pts %" GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_PTS (GST_BUFFER_CAST (data))),
- GST_TIME_ARGS (GST_BUFFER_DTS (GST_BUFFER_CAST (data))));
- /* If an EOS went through, a buffer would be invalid */
- fail_if (consist->eos, "Buffer received after EOS on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- /* Buffers need to be preceded by a segment event */
- fail_unless (consist->segment, "Buffer received without segment "
- "on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- } else if (GST_IS_EVENT (data)) {
- GstEvent *event = (GstEvent *) data;
-
- GST_DEBUG_OBJECT (pad, "Event : %s", GST_EVENT_TYPE_NAME (event));
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- /* getting two flush_start in a row seems to be okay
- fail_if (consist->flushing, "Received another FLUSH_START");
- */
- consist->flushing = TRUE;
- break;
- case GST_EVENT_FLUSH_STOP:
- /* Receiving a flush-stop is only valid after receiving a flush-start */
- fail_unless (consist->flushing,
- "Received a FLUSH_STOP without a FLUSH_START on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- fail_if (consist->eos, "Received a FLUSH_STOP after an EOS on "
- "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- consist->flushing = consist->expect_flush = FALSE;
- break;
- case GST_EVENT_STREAM_START:
- fail_if (consist->saw_serialized_event && !consist->saw_stream_start,
- "Got a STREAM_START event after a serialized event on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- consist->saw_stream_start = TRUE;
- break;
- case GST_EVENT_CAPS:
- /* ok to have these before segment event */
- /* FIXME check order more precisely, if so spec'ed somehow ? */
- break;
- case GST_EVENT_SEGMENT:
- fail_if ((consist->expect_flush && consist->flushing),
- "Received SEGMENT while in a flushing seek on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- consist->segment = TRUE;
- consist->eos = FALSE;
- break;
- case GST_EVENT_EOS:
- /* FIXME : not 100% sure about whether two eos in a row is valid */
- fail_if (consist->eos, "Received EOS just after another EOS on "
- "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- consist->eos = TRUE;
- consist->segment = FALSE;
- break;
- case GST_EVENT_TAG:
- GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT,
- gst_event_get_structure (event));
- /* fall through */
- default:
- if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_IS_DOWNSTREAM (event)) {
- fail_if (consist->eos, "Event received after EOS");
- fail_unless (consist->segment, "Event %s received before segment "
- "on pad %s:%s", GST_EVENT_TYPE_NAME (event),
- GST_DEBUG_PAD_NAME (pad));
- }
- /* FIXME : Figure out what to do for other events */
- break;
- }
- if (GST_EVENT_IS_SERIALIZED (event)) {
- fail_if (!consist->saw_stream_start
- && GST_EVENT_TYPE (event) != GST_EVENT_STREAM_START,
- "Got a serialized event (%s) before a STREAM_START on pad %s:%s",
- GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad));
- consist->saw_serialized_event = TRUE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-sink_pad_data_cb (GstPad * pad, GstPadProbeInfo * info,
- GstStreamConsistency * consist)
-{
- GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info);
-
- GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing,
- consist->segment, consist->eos, consist->expect_flush);
-
- if (GST_IS_BUFFER (data)) {
- GST_DEBUG_OBJECT (pad, "Buffer %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (GST_BUFFER (data))));
- /* If an EOS went through, a buffer would be invalid */
- fail_if (consist->eos, "Buffer received after EOS on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- /* Buffers need to be preceded by a segment event */
- fail_unless (consist->segment, "Buffer received without segment "
- "on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- } else if (GST_IS_EVENT (data)) {
- GstEvent *event = (GstEvent *) data;
-
- GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event));
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- {
- GstSeekFlags flags;
-
- gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL,
- NULL);
- consist->expect_flush =
- ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
- break;
- }
- case GST_EVENT_SEGMENT:
- fail_if ((consist->expect_flush && consist->flushing),
- "Received SEGMENT while in a flushing seek on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- consist->segment = TRUE;
- consist->eos = FALSE;
- break;
- default:
- /* FIXME : Figure out what to do for other events */
- break;
- }
- }
-
- return TRUE;
-}
-
-static void
-add_pad (GstStreamConsistency * consist, GstPad * pad)
-{
- GstStreamConsistencyProbe *p;
- GstPadDirection dir;
-
- p = g_new0 (GstStreamConsistencyProbe, 1);
- p->pad = g_object_ref (pad);
- dir = gst_pad_get_direction (pad);
- if (dir == GST_PAD_SRC) {
-
- p->probeid =
- gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
- (GstPadProbeCallback) source_pad_data_cb, consist, NULL);
-
- } else if (dir == GST_PAD_SINK) {
- p->probeid =
- gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
- (GstPadProbeCallback) sink_pad_data_cb, consist, NULL);
- }
- consist->pads = g_list_prepend (consist->pads, p);
-}
-
-/**
- * gst_consistency_checker_new: (skip)
- * @pad: The #GstPad on which the dataflow will be checked.
- *
- * Sets up a data probe on the given pad which will raise assertions if the
- * data flow is inconsistent.
- *
- * Returns: A #GstStreamConsistency structure used to track data flow.
- */
-GstStreamConsistency *
-gst_consistency_checker_new (GstPad * pad)
-{
- GstStreamConsistency *consist;
-
- g_return_val_if_fail (pad != NULL, NULL);
-
- consist = g_new0 (GstStreamConsistency, 1);
-
- if (!consist->pads) {
- consist->parent = GST_OBJECT_PARENT (pad);
- }
- add_pad (consist, pad);
- return consist;
-}
-
-/**
- * gst_consistency_checker_add_pad:
- * @consist: The #GstStreamConsistency handle
- * @pad: The #GstPad on which the dataflow will be checked.
- *
- * Sets up a data probe on the given pad which will raise assertions if the
- * data flow is inconsistent.
- *
- * Returns: %TRUE if the pad was added
- */
-gboolean
-gst_consistency_checker_add_pad (GstStreamConsistency * consist, GstPad * pad)
-{
- g_return_val_if_fail (consist != NULL, FALSE);
- g_return_val_if_fail (pad != NULL, FALSE);
- g_return_val_if_fail (GST_OBJECT_PARENT (pad) == consist->parent, FALSE);
-
- add_pad (consist, pad);
- return TRUE;
-}
-
-/**
- * gst_consistency_checker_reset:
- * @consist: The #GstStreamConsistency to reset.
- *
- * Reset the stream checker's internal variables.
- */
-
-void
-gst_consistency_checker_reset (GstStreamConsistency * consist)
-{
- consist->flushing = FALSE;
- consist->segment = FALSE;
- consist->eos = FALSE;
- consist->expect_flush = FALSE;
- consist->saw_serialized_event = FALSE;
- consist->saw_stream_start = FALSE;
-}
-
-/**
- * gst_consistency_checker_free:
- * @consist: The #GstStreamConsistency to free.
- *
- * Frees the allocated data and probes associated with @consist.
- */
-
-void
-gst_consistency_checker_free (GstStreamConsistency * consist)
-{
- GList *node;
- GstStreamConsistencyProbe *p;
-
- /* Remove the data probes */
- for (node = consist->pads; node; node = g_list_next (node)) {
- p = (GstStreamConsistencyProbe *) node->data;
- gst_pad_remove_probe (p->pad, p->probeid);
- gst_object_unref (p->pad);
- g_free (p);
- }
- g_list_free (consist->pads);
- g_free (consist);
-}
diff --git a/libs/gst/check/gstconsistencychecker.h b/libs/gst/check/gstconsistencychecker.h
deleted file mode 100644
index 03ce583a8f..0000000000
--- a/libs/gst/check/gstconsistencychecker.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* GStreamer
- *
- * unit testing helper lib
- *
- * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CONSISTENCY_CHECKER_H__
-#define __GST_CONSISTENCY_CHECKER_H__
-
-#include <gst/check/gstcheck.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstStreamConsistency:
- *
- * Opaque consistency checker handle.
- */
-typedef struct _GstStreamConsistency GstStreamConsistency;
-
-GST_CHECK_API
-GstStreamConsistency * gst_consistency_checker_new (GstPad * pad);
-
-GST_CHECK_API
-gboolean gst_consistency_checker_add_pad (GstStreamConsistency * consist,
- GstPad * pad);
-
-GST_CHECK_API
-void gst_consistency_checker_reset (GstStreamConsistency * consist);
-
-GST_CHECK_API
-void gst_consistency_checker_free (GstStreamConsistency * consist);
-
-G_END_DECLS
-
-#endif /* __GST_CONSISTENCY_CHECKER_H__ */
diff --git a/libs/gst/check/gstharness.c b/libs/gst/check/gstharness.c
deleted file mode 100644
index fc1ab0dafe..0000000000
--- a/libs/gst/check/gstharness.c
+++ /dev/null
@@ -1,3517 +0,0 @@
-/* GstHarness - A test-harness for GStreamer testing
- *
- * Copyright (C) 2012-2015 Pexip <pexip.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:gstharness
- * @title: GstHarness
- * @short_description: A test-harness for writing GStreamer unit tests
- * @see_also: #GstTestClock
- *
- * #GstHarness is meant to make writing unit test for GStreamer much easier.
- * It can be thought of as a way of treating a #GstElement as a black box,
- * deterministically feeding it data, and controlling what data it outputs.
- *
- * The basic structure of #GstHarness is two "floating" #GstPads that connect
- * to the harnessed #GstElement src and sink #GstPads like so:
- *
- * |[
- * __________________________
- * _____ | _____ _____ | _____
- * | | | | | | | | | |
- * | src |--+-| sink| Element | src |-+--| sink|
- * |_____| | |_____| |_____| | |_____|
- * |__________________________|
- *
- * ]|
- *
- * With this, you can now simulate any environment the #GstElement might find
- * itself in. By specifying the #GstCaps of the harness #GstPads, using
- * functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(),
- * you can test how the #GstElement interacts with different caps sets.
- *
- * Your harnessed #GstElement can of course also be a bin, and using
- * gst_harness_new_parse() supporting standard gst-launch syntax, you can
- * easily test a whole pipeline instead of just one element.
- *
- * You can then go on to push #GstBuffers and #GstEvents on to the srcpad,
- * using functions like gst_harness_push() and gst_harness_push_event(), and
- * then pull them out to examine them with gst_harness_pull() and
- * gst_harness_pull_event().
- *
- * ## A simple buffer-in buffer-out example
- *
- * |[<!-- language="C" -->
- * #include <gst/gst.h>
- * #include <gst/check/gstharness.h>
- * GstHarness *h;
- * GstBuffer *in_buf;
- * GstBuffer *out_buf;
- *
- * // attach the harness to the src and sink pad of GstQueue
- * h = gst_harness_new ("queue");
- *
- * // we must specify a caps before pushing buffers
- * gst_harness_set_src_caps_str (h, "mycaps");
- *
- * // create a buffer of size 42
- * in_buf = gst_harness_create_buffer (h, 42);
- *
- * // push the buffer into the queue
- * gst_harness_push (h, in_buf);
- *
- * // pull the buffer from the queue
- * out_buf = gst_harness_pull (h);
- *
- * // validate the buffer in is the same as buffer out
- * fail_unless (in_buf == out_buf);
- *
- * // cleanup
- * gst_buffer_unref (out_buf);
- * gst_harness_teardown (h);
- *
- * ]|
- *
- * Another main feature of the #GstHarness is its integration with the
- * #GstTestClock. Operating the #GstTestClock can be very challenging, but
- * #GstHarness simplifies some of the most desired actions a lot, like wanting
- * to manually advance the clock while at the same time releasing a #GstClockID
- * that is waiting, with functions like gst_harness_crank_single_clock_wait().
- *
- * #GstHarness also supports sub-harnesses, as a way of generating and
- * validating data. A sub-harness is another #GstHarness that is managed by
- * the "parent" harness, and can either be created by using the standard
- * gst_harness_new type functions directly on the (GstHarness *)->src_harness,
- * or using the much more convenient gst_harness_add_src() or
- * gst_harness_add_sink_parse(). If you have a decoder-element you want to test,
- * (like vp8dec) it can be very useful to add a src-harness with both a
- * src-element (videotestsrc) and an encoder (vp8enc) to feed the decoder data
- * with different configurations, by simply doing:
- *
- * |[<!-- language="C" -->
- * GstHarness * h = gst_harness_new (h, "vp8dec");
- * gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE);
- * ]|
- *
- * and then feeding it data with:
- *
- * |[<!-- language="C" -->
- * gst_harness_push_from_src (h);
- * ]|
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* we have code with side effects in asserts, so make sure they are active */
-#ifdef G_DISABLE_ASSERT
-#error "GstHarness must be compiled with G_DISABLE_ASSERT undefined"
-#endif
-
-#include "gstharness.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-static void gst_harness_stress_free (GstHarnessThread * t);
-
-#define HARNESS_KEY "harness"
-#define HARNESS_REF "harness-ref"
-#define HARNESS_LOCK(h) g_mutex_lock (&(h)->priv->priv_mutex)
-#define HARNESS_UNLOCK(h) g_mutex_unlock (&(h)->priv->priv_mutex)
-
-static GstStaticPadTemplate hsrctemplate = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-static GstStaticPadTemplate hsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-typedef struct
-{
- GType api;
- GstStructure *params;
-} ProposeMeta;
-
-static void
-propose_meta_clear (ProposeMeta * meta)
-{
- if (meta->params)
- gst_structure_free (meta->params);
-}
-
-struct _GstHarnessPrivate
-{
- gchar *element_sinkpad_name;
- gchar *element_srcpad_name;
-
- GstCaps *src_caps;
- GstCaps *sink_caps;
-
- gboolean forwarding;
- GstPad *sink_forward_pad;
- GstTestClock *testclock;
-
- gint recv_buffers;
- gint recv_events;
- gint recv_upstream_events;
-
- GAsyncQueue *buffer_queue;
- GAsyncQueue *src_event_queue;
- GAsyncQueue *sink_event_queue;
-
- GstClockTime latency_min;
- GstClockTime latency_max;
- gboolean is_live;
-
- gboolean has_clock_wait;
- gboolean drop_buffers;
- GstClockTime last_push_ts;
-
- GstBufferPool *pool;
- GstAllocator *allocator;
- GstAllocationParams allocation_params;
- GstAllocator *propose_allocator;
- GstAllocationParams propose_allocation_params;
-
- GArray *propose_allocation_metas;
-
- gboolean blocking_push_mode;
- GCond blocking_push_cond;
- GMutex blocking_push_mutex;
- GMutex priv_mutex;
-
- GCond buf_or_eos_cond;
- GMutex buf_or_eos_mutex;
- gboolean eos_received;
-
- GPtrArray *stress;
-};
-
-static GstFlowReturn
-gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
-{
- GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
- GstHarnessPrivate *priv = h->priv;
- (void) parent;
- g_assert (h != NULL);
- g_mutex_lock (&priv->blocking_push_mutex);
- g_atomic_int_inc (&priv->recv_buffers);
-
- if (priv->drop_buffers) {
- gst_buffer_unref (buffer);
- } else {
- g_mutex_lock (&priv->buf_or_eos_mutex);
- g_async_queue_push (priv->buffer_queue, buffer);
- g_cond_signal (&priv->buf_or_eos_cond);
- g_mutex_unlock (&priv->buf_or_eos_mutex);
- }
-
-
- if (priv->blocking_push_mode) {
- g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex);
- }
- g_mutex_unlock (&priv->blocking_push_mutex);
-
- return GST_FLOW_OK;
-}
-
-static gboolean
-gst_harness_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
- GstHarnessPrivate *priv = h->priv;
- (void) parent;
- g_assert (h != NULL);
- g_atomic_int_inc (&priv->recv_upstream_events);
- g_async_queue_push (priv->src_event_queue, event);
- return TRUE;
-}
-
-static gboolean
-gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
-{
- GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
- GstHarnessPrivate *priv = h->priv;
- gboolean ret = TRUE;
- gboolean forward;
-
- g_assert (h != NULL);
- (void) parent;
- g_atomic_int_inc (&priv->recv_events);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_STREAM_START:
- case GST_EVENT_CAPS:
- case GST_EVENT_SEGMENT:
- forward = TRUE;
- break;
- default:
- forward = FALSE;
- break;
- }
-
- HARNESS_LOCK (h);
- if (priv->forwarding && forward && priv->sink_forward_pad) {
- GstPad *fwdpad = gst_object_ref (priv->sink_forward_pad);
- HARNESS_UNLOCK (h);
- ret = gst_pad_push_event (fwdpad, event);
- gst_object_unref (fwdpad);
- HARNESS_LOCK (h);
- } else {
- if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
- g_mutex_lock (&priv->buf_or_eos_mutex);
- priv->eos_received = TRUE;
- g_cond_signal (&priv->buf_or_eos_cond);
- g_mutex_unlock (&priv->buf_or_eos_mutex);
- }
- g_async_queue_push (priv->sink_event_queue, event);
- }
- HARNESS_UNLOCK (h);
-
- return ret;
-}
-
-static void
-gst_harness_decide_allocation (GstHarness * h, GstCaps * caps)
-{
- GstHarnessPrivate *priv = h->priv;
- GstQuery *query;
- GstAllocator *allocator;
- GstAllocationParams params;
- GstBufferPool *pool = NULL;
- guint size, min, max;
-
- query = gst_query_new_allocation (caps, FALSE);
- gst_pad_peer_query (h->srcpad, query);
-
- if (gst_query_get_n_allocation_params (query) > 0) {
- gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
- } else {
- allocator = NULL;
- gst_allocation_params_init (&params);
- }
-
- if (gst_query_get_n_allocation_pools (query) > 0) {
- gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
-#if 0
- /* Most elements create their own pools if pool == NULL. Not sure if we
- * want to do that in the harness since we may want to test the pool
- * implementation of the elements. Not creating a pool will however ignore
- * the returned size. */
- if (pool == NULL)
- pool = gst_buffer_pool_new ();
-#endif
- } else {
- pool = NULL;
- size = min = max = 0;
- }
- gst_query_unref (query);
-
- if (pool) {
- GstStructure *config = gst_buffer_pool_get_config (pool);
- gst_buffer_pool_config_set_params (config, caps, size, min, max);
- gst_buffer_pool_config_set_allocator (config, allocator, &params);
- gst_buffer_pool_set_config (pool, config);
- }
-
- if (pool != priv->pool) {
- if (priv->pool != NULL)
- gst_buffer_pool_set_active (priv->pool, FALSE);
- if (pool)
- gst_buffer_pool_set_active (pool, TRUE);
- }
-
- priv->allocation_params = params;
- if (priv->allocator)
- gst_object_unref (priv->allocator);
- priv->allocator = allocator;
- if (priv->pool)
- gst_object_unref (priv->pool);
- priv->pool = pool;
-}
-
-static void
-gst_harness_negotiate (GstHarness * h)
-{
- GstCaps *caps;
-
- caps = gst_pad_get_current_caps (h->srcpad);
- if (caps != NULL) {
- gst_harness_decide_allocation (h, caps);
- gst_caps_unref (caps);
- } else {
- GST_FIXME_OBJECT (h->srcpad,
- "Cannot negotiate allocation because caps is not set");
- }
-}
-
-static gboolean
-gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
- GstHarnessPrivate *priv = h->priv;
- gboolean res = TRUE;
- g_assert (h != NULL);
-
- // FIXME: forward all queries?
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_LATENCY:
- gst_query_set_latency (query, priv->is_live, priv->latency_min,
- priv->latency_max);
- break;
- case GST_QUERY_CAPS:
- {
- GstCaps *caps, *filter = NULL;
-
- if (priv->sink_caps) {
- caps = gst_caps_ref (priv->sink_caps);
- } else {
- caps = gst_pad_get_pad_template_caps (pad);
- }
-
- gst_query_parse_caps (query, &filter);
- if (filter != NULL) {
- gst_caps_take (&caps,
- gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
- }
-
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- }
- break;
- case GST_QUERY_ALLOCATION:
- {
- HARNESS_LOCK (h);
- if (priv->forwarding && priv->sink_forward_pad != NULL) {
- GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad);
- g_assert (peer != NULL);
- HARNESS_UNLOCK (h);
- res = gst_pad_query (peer, query);
- gst_object_unref (peer);
- HARNESS_LOCK (h);
- } else {
- GstCaps *caps;
- gboolean need_pool;
- guint size;
-
- gst_query_parse_allocation (query, &caps, &need_pool);
-
- /* FIXME: Can this be removed? */
- size = gst_query_get_n_allocation_params (query);
- g_assert_cmpuint (0, ==, size);
- gst_query_add_allocation_param (query,
- priv->propose_allocator, &priv->propose_allocation_params);
-
- if (priv->propose_allocation_metas) {
- guint i;
- for (i = 0; i < priv->propose_allocation_metas->len; i++) {
- ProposeMeta *meta =
- &g_array_index (priv->propose_allocation_metas, ProposeMeta, i);
- gst_query_add_allocation_meta (query, meta->api, meta->params);
- }
- }
-
- GST_DEBUG_OBJECT (pad, "proposing allocation %" GST_PTR_FORMAT,
- priv->propose_allocator);
- }
- HARNESS_UNLOCK (h);
- break;
- }
- case GST_QUERY_CONTEXT:
- HARNESS_LOCK (h);
- if (priv->forwarding && priv->sink_forward_pad != NULL) {
- GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad);
- g_assert (peer != NULL);
- HARNESS_UNLOCK (h);
- res = gst_pad_query (peer, query);
- gst_object_unref (peer);
- } else {
- HARNESS_UNLOCK (h);
- res = gst_pad_query_default (pad, parent, query);
- }
- break;
- default:
- res = gst_pad_query_default (pad, parent, query);
- }
-
- return res;
-}
-
-static gboolean
-gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
-{
- GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
- GstHarnessPrivate *priv = h->priv;
- gboolean res = TRUE;
- g_assert (h != NULL);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_LATENCY:
- gst_query_set_latency (query, priv->is_live, priv->latency_min,
- priv->latency_max);
- break;
- case GST_QUERY_CAPS:
- {
- GstCaps *caps, *filter = NULL;
-
- if (priv->src_caps) {
- caps = gst_caps_ref (priv->src_caps);
- } else {
- caps = gst_pad_get_pad_template_caps (pad);
- }
-
- gst_query_parse_caps (query, &filter);
- if (filter != NULL) {
- gst_caps_take (&caps,
- gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
- }
-
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- }
- break;
- default:
- res = gst_pad_query_default (pad, parent, query);
- }
- return res;
-}
-
-static void
-gst_harness_element_ref (GstHarness * h)
-{
- guint *data;
-
- GST_OBJECT_LOCK (h->element);
- data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
- if (data == NULL) {
- data = g_new0 (guint, 1);
- *data = 1;
- g_object_set_data_full (G_OBJECT (h->element), HARNESS_REF, data, g_free);
- } else {
- (*data)++;
- }
- GST_OBJECT_UNLOCK (h->element);
-}
-
-static guint
-gst_harness_element_unref (GstHarness * h)
-{
- guint *data;
- guint ret;
-
- GST_OBJECT_LOCK (h->element);
- data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
- g_assert (data != NULL);
- (*data)--;
- ret = *data;
- GST_OBJECT_UNLOCK (h->element);
-
- return ret;
-}
-
-static void
-gst_harness_link_element_srcpad (GstHarness * h,
- const gchar * element_srcpad_name)
-{
- GstHarnessPrivate *priv = h->priv;
- GstPad *srcpad = gst_element_get_static_pad (h->element,
- element_srcpad_name);
- GstPadLinkReturn link;
- if (srcpad == NULL)
- srcpad = gst_element_request_pad_simple (h->element, element_srcpad_name);
- g_assert (srcpad);
- link = gst_pad_link (srcpad, h->sinkpad);
- g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
- g_free (priv->element_srcpad_name);
- priv->element_srcpad_name = gst_pad_get_name (srcpad);
-
- gst_object_unref (srcpad);
-}
-
-static void
-gst_harness_link_element_sinkpad (GstHarness * h,
- const gchar * element_sinkpad_name)
-{
- GstHarnessPrivate *priv = h->priv;
- GstPad *sinkpad = gst_element_get_static_pad (h->element,
- element_sinkpad_name);
- GstPadLinkReturn link;
- if (sinkpad == NULL)
- sinkpad = gst_element_request_pad_simple (h->element, element_sinkpad_name);
- g_assert (sinkpad);
- link = gst_pad_link (h->srcpad, sinkpad);
- g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
- g_free (priv->element_sinkpad_name);
- priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
-
- gst_object_unref (sinkpad);
-}
-
-static void
-gst_harness_setup_src_pad (GstHarness * h,
- GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name)
-{
- g_assert (src_tmpl);
- g_assert (h->srcpad == NULL);
-
- /* sending pad */
- h->srcpad = gst_pad_new_from_static_template (src_tmpl, "src");
- g_assert (h->srcpad);
- g_object_set_data (G_OBJECT (h->srcpad), HARNESS_KEY, h);
-
- gst_pad_set_query_function (h->srcpad, gst_harness_src_query);
- gst_pad_set_event_function (h->srcpad, gst_harness_src_event);
-
- gst_pad_set_active (h->srcpad, TRUE);
-
- if (element_sinkpad_name)
- gst_harness_link_element_sinkpad (h, element_sinkpad_name);
-}
-
-static void
-gst_harness_setup_sink_pad (GstHarness * h,
- GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name)
-{
- g_assert (sink_tmpl);
- g_assert (h->sinkpad == NULL);
-
- /* receiving pad */
- h->sinkpad = gst_pad_new_from_static_template (sink_tmpl, "sink");
- g_assert (h->sinkpad);
- g_object_set_data (G_OBJECT (h->sinkpad), HARNESS_KEY, h);
-
- gst_pad_set_chain_function (h->sinkpad, gst_harness_chain);
- gst_pad_set_query_function (h->sinkpad, gst_harness_sink_query);
- gst_pad_set_event_function (h->sinkpad, gst_harness_sink_event);
-
- gst_pad_set_active (h->sinkpad, TRUE);
-
- if (element_srcpad_name)
- gst_harness_link_element_srcpad (h, element_srcpad_name);
-}
-
-static void
-check_element_type (GstElement * element, gboolean * has_sinkpad,
- gboolean * has_srcpad)
-{
- GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element);
- const GList *tmpl_list;
-
- *has_srcpad = element->numsrcpads > 0;
- *has_sinkpad = element->numsinkpads > 0;
-
- tmpl_list = gst_element_class_get_pad_template_list (element_class);
-
- while (tmpl_list) {
- GstPadTemplate *pad_tmpl = (GstPadTemplate *) tmpl_list->data;
- tmpl_list = g_list_next (tmpl_list);
- if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SRC)
- *has_srcpad |= TRUE;
- if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SINK)
- *has_sinkpad |= TRUE;
- }
-}
-
-static void
-turn_async_and_sync_off (GstElement * element)
-{
- GObjectClass *class = G_OBJECT_GET_CLASS (element);
- if (g_object_class_find_property (class, "async"))
- g_object_set (element, "async", FALSE, NULL);
- if (g_object_class_find_property (class, "sync"))
- g_object_set (element, "sync", FALSE, NULL);
-}
-
-static gboolean
-gst_pad_is_request_pad (GstPad * pad)
-{
- GstPadTemplate *temp;
- gboolean is_request;
-
- if (pad == NULL)
- return FALSE;
- temp = gst_pad_get_pad_template (pad);
- if (temp == NULL)
- return FALSE;
- is_request = GST_PAD_TEMPLATE_PRESENCE (temp) == GST_PAD_REQUEST;
- gst_object_unref (temp);
- return is_request;
-}
-
-/**
- * gst_harness_new_empty: (skip)
- *
- * Creates a new empty harness. Use gst_harness_add_element_full() to add
- * an #GstElement to it.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.8
- */
-GstHarness *
-gst_harness_new_empty (void)
-{
- GstHarness *h;
- GstHarnessPrivate *priv;
-
- h = g_new0 (GstHarness, 1);
- g_assert (h != NULL);
- h->priv = g_new0 (GstHarnessPrivate, 1);
- priv = h->priv;
-
- GST_DEBUG ("about to create new harness %p", h);
- priv->last_push_ts = GST_CLOCK_TIME_NONE;
- priv->latency_min = 0;
- priv->latency_max = GST_CLOCK_TIME_NONE;
- priv->is_live = TRUE;
- priv->drop_buffers = FALSE;
- priv->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
-
- priv->buffer_queue = g_async_queue_new_full (
- (GDestroyNotify) gst_buffer_unref);
- priv->src_event_queue = g_async_queue_new_full (
- (GDestroyNotify) gst_event_unref);
- priv->sink_event_queue = g_async_queue_new_full (
- (GDestroyNotify) gst_event_unref);
-
- priv->propose_allocator = NULL;
- gst_allocation_params_init (&priv->propose_allocation_params);
-
- g_mutex_init (&priv->blocking_push_mutex);
- g_cond_init (&priv->blocking_push_cond);
- g_mutex_init (&priv->priv_mutex);
-
- g_mutex_init (&priv->buf_or_eos_mutex);
- g_cond_init (&priv->buf_or_eos_cond);
- priv->eos_received = FALSE;
-
- priv->stress = g_ptr_array_new_with_free_func (
- (GDestroyNotify) gst_harness_stress_free);
-
- /* we have forwarding on as a default */
- gst_harness_set_forwarding (h, TRUE);
-
- return h;
-}
-
-/**
- * gst_harness_add_element_full: (skip)
- * @h: a #GstHarness
- * @element: a #GstElement to add to the harness (transfer none)
- * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
- * %NULL will not create a harness srcpad.
- * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
- * sinkpad that is then linked to the harness srcpad. Can be a static or request
- * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
- * from the element. (Like if the element is a src.)
- * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
- * %NULL will not create a harness sinkpad.
- * @element_srcpad_name: (allow-none): a #gchar with the name of the element
- * srcpad that is then linked to the harness sinkpad, similar to the
- * @element_sinkpad_name.
- *
- * Adds a #GstElement to an empty #GstHarness
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_element_full (GstHarness * h, GstElement * element,
- GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
- GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
-{
- GstClock *element_clock;
- gboolean has_sinkpad, has_srcpad;
-
- g_return_if_fail (element != NULL);
- g_return_if_fail (h->element == NULL);
-
- element_clock = GST_ELEMENT_CLOCK (element);
- h->element = gst_object_ref (element);
- check_element_type (element, &has_sinkpad, &has_srcpad);
-
- /* setup the loose srcpad linked to the element sinkpad */
- if (has_sinkpad)
- gst_harness_setup_src_pad (h, hsrc, element_sinkpad_name);
-
- /* setup the loose sinkpad linked to the element srcpad */
- if (has_srcpad)
- gst_harness_setup_sink_pad (h, hsink, element_srcpad_name);
-
- /* as a harness sink, we should not need sync and async */
- if (has_sinkpad && !has_srcpad)
- turn_async_and_sync_off (h->element);
-
- if (h->srcpad != NULL) {
- gboolean handled;
- gchar *stream_id = g_strdup_printf ("%s-%p",
- GST_OBJECT_NAME (h->element), h);
- handled = gst_pad_push_event (h->srcpad,
- gst_event_new_stream_start (stream_id));
- g_assert (handled);
- g_free (stream_id);
- }
-
- /* if the element already has a testclock attached,
- we replace our own with it, if no clock we attach the testclock */
- if (element_clock) {
- if (GST_IS_TEST_CLOCK (element_clock)) {
- gst_object_replace ((GstObject **) & h->priv->testclock,
- (GstObject *) GST_ELEMENT_CLOCK (element));
- }
- } else {
- gst_harness_use_testclock (h);
- }
-
- /* don't start sources, they start producing data! */
- if (has_sinkpad)
- gst_harness_play (h);
-
- gst_harness_element_ref (h);
-
- GST_DEBUG ("added element to harness %p "
- "with element_srcpad_name (%p, %s, %s) and element_sinkpad_name (%p, %s, %s)",
- h, h->srcpad, GST_DEBUG_PAD_NAME (h->srcpad),
- h->sinkpad, GST_DEBUG_PAD_NAME (h->sinkpad));
-}
-
-/**
- * gst_harness_new_full: (skip)
- * @element: a #GstElement to attach the harness to (transfer none)
- * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
- * %NULL will not create a harness srcpad.
- * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
- * sinkpad that is then linked to the harness srcpad. Can be a static or request
- * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
- * from the element. (Like if the element is a src.)
- * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
- * %NULL will not create a harness sinkpad.
- * @element_srcpad_name: (allow-none): a #gchar with the name of the element
- * srcpad that is then linked to the harness sinkpad, similar to the
- * @element_sinkpad_name.
- *
- * Creates a new harness.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new_full (GstElement * element,
- GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
- GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
-{
- GstHarness *h;
- h = gst_harness_new_empty ();
- gst_harness_add_element_full (h, element,
- hsrc, element_sinkpad_name, hsink, element_srcpad_name);
- return h;
-}
-
-/**
- * gst_harness_new_with_element: (skip)
- * @element: a #GstElement to attach the harness to (transfer none)
- * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
- * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
- * sinkpad
- * @element_srcpad_name: (allow-none): a #gchar with the name of the element
- * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
- * srcpad
- *
- * Creates a new harness. Works in the same way as gst_harness_new_full(), only
- * that generic padtemplates are used for the harness src and sinkpads, which
- * will be sufficient in most usecases.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new_with_element (GstElement * element,
- const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
-{
- return gst_harness_new_full (element,
- &hsrctemplate, element_sinkpad_name, &hsinktemplate, element_srcpad_name);
-}
-
-/**
- * gst_harness_new_with_padnames: (skip)
- * @element_name: a #gchar describing the #GstElement name
- * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
- * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
- * sinkpad
- * @element_srcpad_name: (allow-none): a #gchar with the name of the element
- * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
- * srcpad
- *
- * Creates a new harness. Works like gst_harness_new_with_element(),
- * except you specify the factoryname of the #GstElement
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new_with_padnames (const gchar * element_name,
- const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
-{
- GstHarness *h;
- GstElement *element = gst_element_factory_make (element_name, NULL);
- g_assert (element != NULL);
-
- h = gst_harness_new_with_element (element, element_sinkpad_name,
- element_srcpad_name);
- gst_object_unref (element);
- return h;
-}
-
-/**
- * gst_harness_new_with_templates: (skip)
- * @element_name: a #gchar describing the #GstElement name
- * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
- * %NULL will not create a harness srcpad.
- * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
- * %NULL will not create a harness sinkpad.
- *
- * Creates a new harness, like gst_harness_new_full(), except it
- * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new_with_templates (const gchar * element_name,
- GstStaticPadTemplate * hsrc, GstStaticPadTemplate * hsink)
-{
- GstHarness *h;
- GstElement *element = gst_element_factory_make (element_name, NULL);
- g_assert (element != NULL);
-
- h = gst_harness_new_full (element, hsrc, "sink", hsink, "src");
- gst_object_unref (element);
- return h;
-}
-
-/**
- * gst_harness_new: (skip)
- * @element_name: a #gchar describing the #GstElement name
- *
- * Creates a new harness. Works like gst_harness_new_with_padnames(), except it
- * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new (const gchar * element_name)
-{
- return gst_harness_new_with_padnames (element_name, "sink", "src");
-}
-
-/**
- * gst_harness_add_parse: (skip)
- * @h: a #GstHarness
- * @launchline: a #gchar describing a gst-launch type line
- *
- * Parses the @launchline and puts that in a #GstBin,
- * and then attches the supplied #GstHarness to the bin.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_parse (GstHarness * h, const gchar * launchline)
-{
- GstBin *bin;
- gchar *desc;
- GstPad *pad;
- GstIterator *iter;
- gboolean done = FALSE;
- GError *error = NULL;
-
- g_return_if_fail (launchline != NULL);
-
- desc = g_strdup_printf ("bin.( %s )", launchline);
- bin =
- (GstBin *) gst_parse_launch_full (desc, NULL, GST_PARSE_FLAG_FATAL_ERRORS,
- &error);
-
- if (G_UNLIKELY (error != NULL)) {
- g_error ("Unable to create pipeline '%s': %s", desc, error->message);
- }
- g_free (desc);
-
- /* find pads and ghost them if necessary */
- if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC)) != NULL) {
- gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
- gst_object_unref (pad);
- }
- if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK)) != NULL) {
- gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
- gst_object_unref (pad);
- }
-
- iter = gst_bin_iterate_sinks (bin);
- while (!done) {
- GValue item = { 0, };
-
- switch (gst_iterator_next (iter, &item)) {
- case GST_ITERATOR_OK:
- turn_async_and_sync_off (GST_ELEMENT (g_value_get_object (&item)));
- g_value_reset (&item);
- break;
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- gst_object_unref (bin);
- gst_iterator_free (iter);
- g_return_if_reached ();
- break;
- }
- }
- gst_iterator_free (iter);
-
- gst_harness_add_element_full (h, GST_ELEMENT_CAST (bin),
- &hsrctemplate, "sink", &hsinktemplate, "src");
- gst_object_unref (bin);
-}
-
-/**
- * gst_harness_new_parse: (skip)
- * @launchline: a #gchar describing a gst-launch type line
- *
- * Creates a new harness, parsing the @launchline and putting that in a #GstBin,
- * and then attches the harness to the bin.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
- * not be created
- *
- * Since: 1.6
- */
-GstHarness *
-gst_harness_new_parse (const gchar * launchline)
-{
- GstHarness *h;
- h = gst_harness_new_empty ();
- gst_harness_add_parse (h, launchline);
- return h;
-}
-
-/**
- * gst_harness_teardown:
- * @h: a #GstHarness
- *
- * Tears down a @GstHarness, freeing all resources allocated using it.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_teardown (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
-
- if (priv->blocking_push_mode) {
- g_mutex_lock (&priv->blocking_push_mutex);
- priv->blocking_push_mode = FALSE;
- g_cond_signal (&priv->blocking_push_cond);
- g_mutex_unlock (&priv->blocking_push_mutex);
- }
-
- if (h->src_harness)
- gst_harness_teardown (h->src_harness);
- h->src_harness = NULL;
-
- HARNESS_LOCK (h);
- gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL);
- HARNESS_UNLOCK (h);
-
- if (h->sink_harness)
- gst_harness_teardown (h->sink_harness);
- h->sink_harness = NULL;
-
- if (h->srcpad) {
- if (gst_pad_is_request_pad (GST_PAD_PEER (h->srcpad)))
- gst_element_release_request_pad (h->element, GST_PAD_PEER (h->srcpad));
- g_free (priv->element_sinkpad_name);
-
- gst_pad_set_active (h->srcpad, FALSE);
-
- /* Make sure our funcs are not called after harness is teared down since
- * they try to access this harness through pad data */
- GST_PAD_STREAM_LOCK (h->srcpad);
- gst_pad_set_event_function (h->srcpad, NULL);
- gst_pad_set_query_function (h->srcpad, NULL);
- GST_PAD_STREAM_UNLOCK (h->srcpad);
-
- gst_object_unref (h->srcpad);
- }
- h->srcpad = NULL;
-
- if (h->sinkpad) {
- if (gst_pad_is_request_pad (GST_PAD_PEER (h->sinkpad)))
- gst_element_release_request_pad (h->element, GST_PAD_PEER (h->sinkpad));
- g_free (priv->element_srcpad_name);
-
- gst_pad_set_active (h->sinkpad, FALSE);
-
- /* Make sure our funcs are not called after harness is teared down since
- * they try to access this harness through pad data */
- GST_PAD_STREAM_LOCK (h->sinkpad);
- gst_pad_set_chain_function (h->sinkpad, NULL);
- gst_pad_set_event_function (h->sinkpad, NULL);
- gst_pad_set_query_function (h->sinkpad, NULL);
- GST_PAD_STREAM_UNLOCK (h->sinkpad);
-
- gst_object_unref (h->sinkpad);
- }
- h->sinkpad = NULL;
-
- if (priv->src_caps)
- gst_caps_unref (priv->src_caps);
- priv->src_caps = NULL;
-
- if (priv->sink_caps)
- gst_caps_unref (priv->sink_caps);
- priv->sink_caps = NULL;
-
- gst_object_replace ((GstObject **) & priv->propose_allocator, NULL);
- gst_object_replace ((GstObject **) & priv->allocator, NULL);
- gst_object_replace ((GstObject **) & priv->pool, NULL);
-
- if (priv->propose_allocation_metas)
- g_array_unref (priv->propose_allocation_metas);
- priv->propose_allocation_metas = NULL;
-
- /* if we hold the last ref, set to NULL */
- if (h->element != NULL && gst_harness_element_unref (h) == 0) {
- gboolean state_change;
- GstState state, pending;
- state_change = gst_element_set_state (h->element, GST_STATE_NULL);
- g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
- state_change = gst_element_get_state (h->element, &state, &pending, 0);
- g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
- g_assert (state == GST_STATE_NULL);
- }
-
- g_cond_clear (&priv->blocking_push_cond);
- g_mutex_clear (&priv->blocking_push_mutex);
- g_mutex_clear (&priv->priv_mutex);
-
- g_mutex_clear (&priv->buf_or_eos_mutex);
- g_cond_clear (&priv->buf_or_eos_cond);
- priv->eos_received = FALSE;
-
- g_async_queue_unref (priv->buffer_queue);
- priv->buffer_queue = NULL;
- g_async_queue_unref (priv->src_event_queue);
- priv->src_event_queue = NULL;
- g_async_queue_unref (priv->sink_event_queue);
- priv->sink_event_queue = NULL;
-
- g_ptr_array_unref (priv->stress);
- priv->stress = NULL;
-
- if (h->element) {
- gst_object_unref (h->element);
- h->element = NULL;
- }
-
- gst_object_replace ((GstObject **) & priv->testclock, NULL);
-
- g_free (h->priv);
- h->priv = NULL;
- g_free (h);
-}
-
-/**
- * gst_harness_add_element_src_pad:
- * @h: a #GstHarness
- * @srcpad: a #GstPad to link to the harness sinkpad
- *
- * Links the specified #GstPad the @GstHarness sinkpad. This can be useful if
- * perhaps the srcpad did not exist at the time of creating the harness,
- * like a demuxer that provides a sometimes-pad after receiving data.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad)
-{
- GstHarnessPrivate *priv = h->priv;
- GstPadLinkReturn link;
- if (h->sinkpad == NULL)
- gst_harness_setup_sink_pad (h, &hsinktemplate, NULL);
- link = gst_pad_link (srcpad, h->sinkpad);
- g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
- g_free (priv->element_srcpad_name);
- priv->element_srcpad_name = gst_pad_get_name (srcpad);
-}
-
-/**
- * gst_harness_add_element_sink_pad:
- * @h: a #GstHarness
- * @sinkpad: a #GstPad to link to the harness srcpad
- *
- * Links the specified #GstPad the @GstHarness srcpad.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad)
-{
- GstHarnessPrivate *priv = h->priv;
- GstPadLinkReturn link;
- if (h->srcpad == NULL)
- gst_harness_setup_src_pad (h, &hsrctemplate, NULL);
- link = gst_pad_link (h->srcpad, sinkpad);
- g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
- g_free (priv->element_sinkpad_name);
- priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
-}
-
-/**
- * gst_harness_set_src_caps:
- * @h: a #GstHarness
- * @caps: (transfer full): a #GstCaps to set on the harness srcpad
- *
- * Sets the @GstHarness srcpad caps. This must be done before any buffers
- * can legally be pushed from the harness to the element.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_src_caps (GstHarness * h, GstCaps * caps)
-{
- GstHarnessPrivate *priv = h->priv;
- GstSegment segment;
- gboolean handled;
-
- handled = gst_pad_push_event (h->srcpad, gst_event_new_caps (caps));
- g_assert (handled);
- gst_caps_take (&priv->src_caps, caps);
-
- gst_segment_init (&segment, GST_FORMAT_TIME);
- handled = gst_pad_push_event (h->srcpad, gst_event_new_segment (&segment));
- g_assert (handled);
-}
-
-/**
- * gst_harness_set_sink_caps:
- * @h: a #GstHarness
- * @caps: (transfer full): a #GstCaps to set on the harness sinkpad
- *
- * Sets the @GstHarness sinkpad caps.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps)
-{
- GstHarnessPrivate *priv = h->priv;
-
- gst_caps_take (&priv->sink_caps, caps);
- gst_pad_push_event (h->sinkpad, gst_event_new_reconfigure ());
-}
-
-/**
- * gst_harness_set_caps:
- * @h: a #GstHarness
- * @in: (transfer full): a #GstCaps to set on the harness srcpad
- * @out: (transfer full): a #GstCaps to set on the harness sinkpad
- *
- * Sets the @GstHarness srcpad and sinkpad caps.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out)
-{
- gst_harness_set_sink_caps (h, out);
- gst_harness_set_src_caps (h, in);
-}
-
-/**
- * gst_harness_set_src_caps_str:
- * @h: a #GstHarness
- * @str: a @gchar describing a #GstCaps to set on the harness srcpad
- *
- * Sets the @GstHarness srcpad caps using a string. This must be done before
- * any buffers can legally be pushed from the harness to the element.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_src_caps_str (GstHarness * h, const gchar * str)
-{
- gst_harness_set_src_caps (h, gst_caps_from_string (str));
-}
-
-/**
- * gst_harness_set_sink_caps_str:
- * @h: a #GstHarness
- * @str: a @gchar describing a #GstCaps to set on the harness sinkpad
- *
- * Sets the @GstHarness sinkpad caps using a string.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str)
-{
- gst_harness_set_sink_caps (h, gst_caps_from_string (str));
-}
-
-/**
- * gst_harness_set_caps_str:
- * @h: a #GstHarness
- * @in: a @gchar describing a #GstCaps to set on the harness srcpad
- * @out: a @gchar describing a #GstCaps to set on the harness sinkpad
- *
- * Sets the @GstHarness srcpad and sinkpad caps using strings.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_caps_str (GstHarness * h, const gchar * in, const gchar * out)
-{
- gst_harness_set_sink_caps_str (h, out);
- gst_harness_set_src_caps_str (h, in);
-}
-
-/**
- * gst_harness_use_systemclock:
- * @h: a #GstHarness
- *
- * Sets the system #GstClock on the @GstHarness #GstElement
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_use_systemclock (GstHarness * h)
-{
- GstClock *clock = gst_system_clock_obtain ();
- g_assert (clock != NULL);
- gst_element_set_clock (h->element, clock);
- gst_object_unref (clock);
-}
-
-/**
- * gst_harness_use_testclock:
- * @h: a #GstHarness
- *
- * Sets the #GstTestClock on the #GstHarness #GstElement
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_use_testclock (GstHarness * h)
-{
- gst_element_set_clock (h->element, GST_CLOCK_CAST (h->priv->testclock));
-}
-
-/**
- * gst_harness_get_testclock:
- * @h: a #GstHarness
- *
- * Get the #GstTestClock. Useful if specific operations on the testclock is
- * needed.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstTestClock, or %NULL if the testclock is not
- * present.
- *
- * Since: 1.6
- */
-GstTestClock *
-gst_harness_get_testclock (GstHarness * h)
-{
- return gst_object_ref (h->priv->testclock);
-}
-
-/**
- * gst_harness_set_time:
- * @h: a #GstHarness
- * @time: a #GstClockTime to advance the clock to
- *
- * Advance the #GstTestClock to a specific time.
- *
- * MT safe.
- *
- * Returns: a @gboolean %TRUE if the time could be set. %FALSE if not.
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_set_time (GstHarness * h, GstClockTime time)
-{
- gst_test_clock_set_time (h->priv->testclock, time);
- return TRUE;
-}
-
-/**
- * gst_harness_wait_for_clock_id_waits:
- * @h: a #GstHarness
- * @waits: a #guint describing the numbers of #GstClockID registered with
- * the #GstTestClock
- * @timeout: a #guint describing how many seconds to wait for @waits to be true
- *
- * Waits for @timeout seconds until @waits number of #GstClockID waits is
- * registered with the #GstTestClock. Useful for writing deterministic tests,
- * where you want to make sure that an expected number of waits have been
- * reached.
- *
- * MT safe.
- *
- * Returns: a @gboolean %TRUE if the waits have been registered, %FALSE if not.
- * (Could be that it timed out waiting or that more waits than waits was found)
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_wait_for_clock_id_waits (GstHarness * h, guint waits, guint timeout)
-{
- return gst_test_clock_timed_wait_for_multiple_pending_ids (h->priv->testclock,
- waits, timeout * 1000, NULL);
-}
-
-/**
- * gst_harness_crank_single_clock_wait:
- * @h: a #GstHarness
- *
- * A "crank" consists of three steps:
- * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
- * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for.
- * 3: Release the #GstClockID wait.
- * Together, this provides an easy way to not have to think about the details
- * around clocks and time, but still being able to write deterministic tests
- * that are dependent on this. A "crank" can be though of as the notion of
- * manually driving the clock forward to its next logical step.
- *
- * MT safe.
- *
- * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_crank_single_clock_wait (GstHarness * h)
-{
- return gst_test_clock_crank (h->priv->testclock);
-}
-
-/**
- * gst_harness_crank_multiple_clock_waits:
- * @h: a #GstHarness
- * @waits: a #guint describing the number of #GstClockIDs to crank
- *
- * Similar to gst_harness_crank_single_clock_wait(), this is the function to use
- * if your harnessed element(s) are using more then one gst_clock_id_wait.
- * Failing to do so can (and will) make it racy which #GstClockID you actually
- * are releasing, where as this function will process all the waits at the
- * same time, ensuring that one thread can't register another wait before
- * both are released.
- *
- * MT safe.
- *
- * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_crank_multiple_clock_waits (GstHarness * h, guint waits)
-{
- GstTestClock *testclock = h->priv->testclock;
- GList *pending;
- guint processed;
-
- gst_test_clock_wait_for_multiple_pending_ids (testclock, waits, &pending);
- gst_harness_set_time (h, gst_test_clock_id_list_get_latest_time (pending));
- processed = gst_test_clock_process_id_list (testclock, pending);
-
- g_list_free_full (pending, gst_clock_id_unref);
- return processed == waits;
-}
-
-/**
- * gst_harness_play:
- * @h: a #GstHarness
- *
- * This will set the harnessed #GstElement to %GST_STATE_PLAYING.
- * #GstElements without a sink-#GstPad and with the %GST_ELEMENT_FLAG_SOURCE
- * flag set is considered a src #GstElement
- * Non-src #GstElements (like sinks and filters) are automatically set to
- * playing by the #GstHarness, but src #GstElements are not to avoid them
- * starting to produce buffers.
- * Hence, for src #GstElement you must call gst_harness_play() explicitly.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_play (GstHarness * h)
-{
- GstState state, pending;
- gboolean state_change;
- state_change = gst_element_set_state (h->element, GST_STATE_PLAYING);
- g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
- state_change = gst_element_get_state (h->element, &state, &pending, 0);
- g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
- g_assert_cmpint (GST_STATE_PLAYING, ==, state);
-}
-
-/**
- * gst_harness_set_blocking_push_mode:
- * @h: a #GstHarness
- *
- * Setting this will make the harness block in the chain-function, and
- * then release when gst_harness_pull() or gst_harness_try_pull() is called.
- * Can be useful when wanting to control a src-element that is not implementing
- * gst_clock_id_wait() so it can't be controlled by the #GstTestClock, since
- * it otherwise would produce buffers as fast as possible.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_blocking_push_mode (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- priv->blocking_push_mode = TRUE;
-}
-
-/**
- * gst_harness_set_forwarding:
- * @h: a #GstHarness
- * @forwarding: a #gboolean to enable/disable forwarding
- *
- * As a convenience, a src-harness will forward %GST_EVENT_STREAM_START,
- * %GST_EVENT_CAPS and %GST_EVENT_SEGMENT to the main-harness if forwarding
- * is enabled, and forward any sticky-events from the main-harness to
- * the sink-harness. It will also forward the %GST_QUERY_ALLOCATION.
- *
- * If forwarding is disabled, the user will have to either manually push
- * these events from the src-harness using gst_harness_src_push_event(), or
- * create and push them manually. While this will allow full control and
- * inspection of these events, for the most cases having forwarding enabled
- * will be sufficient when writing a test where the src-harness' main function
- * is providing data for the main-harness.
- *
- * Forwarding is enabled by default.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_forwarding (GstHarness * h, gboolean forwarding)
-{
- GstHarnessPrivate *priv = h->priv;
- priv->forwarding = forwarding;
- if (h->src_harness)
- gst_harness_set_forwarding (h->src_harness, forwarding);
- if (h->sink_harness)
- gst_harness_set_forwarding (h->sink_harness, forwarding);
-}
-
-/*
-* Call with HARNESS_LOCK
-*/
-static void
-gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad)
-{
- gst_object_replace ((GstObject **) & h->priv->sink_forward_pad,
- (GstObject *) fwdpad);
-}
-
-/**
- * gst_harness_create_buffer:
- * @h: a #GstHarness
- * @size: a #gsize specifying the size of the buffer
- *
- * Allocates a buffer using a #GstBufferPool if present, or else using the
- * configured #GstAllocator and #GstAllocationParams
- *
- * MT safe.
- *
- * Returns: a #GstBuffer of size @size
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_harness_create_buffer (GstHarness * h, gsize size)
-{
- GstHarnessPrivate *priv = h->priv;
- GstBuffer *ret = NULL;
- GstFlowReturn flow;
-
- if (gst_pad_check_reconfigure (h->srcpad))
- gst_harness_negotiate (h);
-
- if (priv->pool) {
- flow = gst_buffer_pool_acquire_buffer (priv->pool, &ret, NULL);
- g_assert_cmpint (flow, ==, GST_FLOW_OK);
- if (gst_buffer_get_size (ret) != size) {
- GST_DEBUG ("use fallback, pool is configured with a different size (%"
- G_GSIZE_FORMAT " != %" G_GSIZE_FORMAT ")",
- size, gst_buffer_get_size (ret));
- gst_buffer_unref (ret);
- ret = NULL;
- }
- }
-
- if (!ret)
- ret =
- gst_buffer_new_allocate (priv->allocator, size,
- &priv->allocation_params);
-
- g_assert (ret != NULL);
- return ret;
-}
-
-/**
- * gst_harness_push:
- * @h: a #GstHarness
- * @buffer: (transfer full): a #GstBuffer to push
- *
- * Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of
- * interacting with an harnessed element.
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn with the result from the push
- *
- * Since: 1.6
- */
-GstFlowReturn
-gst_harness_push (GstHarness * h, GstBuffer * buffer)
-{
- GstHarnessPrivate *priv = h->priv;
- g_assert (buffer != NULL);
- priv->last_push_ts = GST_BUFFER_TIMESTAMP (buffer);
- return gst_pad_push (h->srcpad, buffer);
-}
-
-/**
- * gst_harness_pull:
- * @h: a #GstHarness
- *
- * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull
- * will timeout in 60 seconds. This is the standard way of getting a buffer
- * from a harnessed #GstElement.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstBuffer or %NULL if timed out.
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_harness_pull (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- GstBuffer *buf = (GstBuffer *) g_async_queue_timeout_pop (priv->buffer_queue,
- G_USEC_PER_SEC * 60);
-
- if (priv->blocking_push_mode) {
- g_mutex_lock (&priv->blocking_push_mutex);
- g_cond_signal (&priv->blocking_push_cond);
- g_mutex_unlock (&priv->blocking_push_mutex);
- }
-
- return buf;
-}
-
-/**
- * gst_harness_pull_until_eos:
- * @h: a #GstHarness
- * @buf: (out) (transfer full): A #GstBuffer, or %NULL if EOS or timeout occures
- * first.
- *
- * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull
- * will block until an EOS event is received, or timeout in 60 seconds.
- * MT safe.
- *
- * Returns: %TRUE on success, %FALSE on timeout.
- *
- * Since: 1.18
- */
-gboolean
-gst_harness_pull_until_eos (GstHarness * h, GstBuffer ** buf)
-{
- GstHarnessPrivate *priv = h->priv;
- gboolean success = TRUE;
- gint64 end_time = g_get_monotonic_time () + 60 * G_TIME_SPAN_SECOND;
-
- g_mutex_lock (&priv->buf_or_eos_mutex);
- while (success) {
- *buf = g_async_queue_try_pop (priv->buffer_queue);
- if (*buf || priv->eos_received)
- break;
- success = g_cond_wait_until (&priv->buf_or_eos_cond,
- &priv->buf_or_eos_mutex, end_time);
- }
- g_mutex_unlock (&priv->buf_or_eos_mutex);
-
- return success;
-}
-
-/**
- * gst_harness_try_pull:
- * @h: a #GstHarness
- *
- * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. Unlike
- * gst_harness_pull this will not wait for any buffers if not any are present,
- * and return %NULL straight away.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_harness_try_pull (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- GstBuffer *buf = (GstBuffer *) g_async_queue_try_pop (priv->buffer_queue);
-
- if (priv->blocking_push_mode) {
- g_mutex_lock (&priv->blocking_push_mutex);
- g_cond_signal (&priv->blocking_push_cond);
- g_mutex_unlock (&priv->blocking_push_mutex);
- }
-
- return buf;
-}
-
-/**
- * gst_harness_push_and_pull:
- * @h: a #GstHarness
- * @buffer: (transfer full): a #GstBuffer to push
- *
- * Basically a gst_harness_push and a gst_harness_pull in one line. Reflects
- * the fact that you often want to do exactly this in your test: Push one buffer
- * in, and inspect the outcome.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstBuffer or %NULL if timed out.
- *
- * Since: 1.6
- */
-GstBuffer *
-gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer)
-{
- gst_harness_push (h, buffer);
- return gst_harness_pull (h);
-}
-
-/**
- * gst_harness_buffers_received:
- * @h: a #GstHarness
- *
- * The total number of #GstBuffers that has arrived on the #GstHarness sinkpad.
- * This number includes buffers that have been dropped as well as buffers
- * that have already been pulled out.
- *
- * MT safe.
- *
- * Returns: a #guint number of buffers received
- *
- * Since: 1.6
- */
-guint
-gst_harness_buffers_received (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_atomic_int_get (&priv->recv_buffers);
-}
-
-/**
- * gst_harness_buffers_in_queue:
- * @h: a #GstHarness
- *
- * The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue
- *
- * MT safe.
- *
- * Returns: a #guint number of buffers in the queue
- *
- * Since: 1.6
- */
-guint
-gst_harness_buffers_in_queue (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_async_queue_length (priv->buffer_queue);
-}
-
-/**
- * gst_harness_set_drop_buffers:
- * @h: a #GstHarness
- * @drop_buffers: a #gboolean specifying to drop outgoing buffers or not
- *
- * When set to %TRUE, instead of placing the buffers arriving from the harnessed
- * #GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers)
-{
- GstHarnessPrivate *priv = h->priv;
- priv->drop_buffers = drop_buffers;
-}
-
-/**
- * gst_harness_take_all_data_as_buffer:
- * @h: a #GstHarness
- *
- * Pulls all pending data from the harness and returns it as a single buffer.
- *
- * Returns: (transfer full): the data as a buffer. Unref with gst_buffer_unref()
- * when no longer needed.
- *
- * Since: 1.14
- */
-GstBuffer *
-gst_harness_take_all_data_as_buffer (GstHarness * h)
-{
- GstHarnessPrivate *priv;
- GstBuffer *ret, *buf;
-
- g_return_val_if_fail (h != NULL, NULL);
-
- priv = h->priv;
-
- g_async_queue_lock (priv->buffer_queue);
-
- ret = g_async_queue_try_pop_unlocked (priv->buffer_queue);
-
- if (ret == NULL) {
- ret = gst_buffer_new ();
- } else {
- /* buffer appending isn't very efficient for larger numbers of buffers
- * or lots of memories, but this function is not performance critical and
- * we can still improve it if and when the need arises. For now KISS. */
- while ((buf = g_async_queue_try_pop_unlocked (priv->buffer_queue)))
- ret = gst_buffer_append (ret, buf);
- }
-
- g_async_queue_unlock (priv->buffer_queue);
-
- return ret;
-}
-
-/**
- * gst_harness_take_all_data: (skip)
- * @h: a #GstHarness
- * @size: (out): the size of the data in bytes
- *
- * Pulls all pending data from the harness and returns it as a single
- * data slice.
- *
- * Returns: (transfer full): a pointer to the data, newly allocated. Free
- * with g_free() when no longer needed. Will return %NULL if there is no
- * data.
- *
- * Since: 1.14
- */
-guint8 *
-gst_harness_take_all_data (GstHarness * h, gsize * size)
-{
- GstBuffer *buf;
- guint8 *data = NULL;
-
- g_return_val_if_fail (h != NULL, NULL);
- g_return_val_if_fail (size != NULL, NULL);
-
- buf = gst_harness_take_all_data_as_buffer (h);
- gst_buffer_extract_dup (buf, 0, -1, (gpointer *) & data, size);
- gst_buffer_unref (buf);
- return data;
-}
-
-/**
- * gst_harness_take_all_data_as_bytes: (rename-to gst_harness_take_all_data)
- * @h: a #GstHarness
- *
- * Pulls all pending data from the harness and returns it as a single #GBytes.
- *
- * Returns: (transfer full): a pointer to the data, newly allocated. Free
- * with g_free() when no longer needed.
- *
- * Since: 1.14
- */
-GBytes *
-gst_harness_take_all_data_as_bytes (GstHarness * h)
-{
- guint8 *data;
- gsize size = 0;
-
- g_return_val_if_fail (h != NULL, NULL);
-
- data = gst_harness_take_all_data (h, &size);
- return g_bytes_new_take (data, size);
-}
-
-
-/**
- * gst_harness_dump_to_file:
- * @h: a #GstHarness
- * @filename: a #gchar with a the name of a file
- *
- * Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue
- * to a file.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_dump_to_file (GstHarness * h, const gchar * filename)
-{
- GError *err = NULL;
- gpointer data;
- gsize size;
-
- data = gst_harness_take_all_data (h, &size);
- if (!g_file_set_contents (filename, data ? data : "", size, &err)) {
- g_error ("GstHarness: Failed to write data to file: %s", err->message);
- g_clear_error (&err);
- }
- g_free (data);
-}
-
-/**
- * gst_harness_get_last_pushed_timestamp:
- * @h: a #GstHarness
- *
- * Get the timestamp of the last #GstBuffer pushed on the #GstHarness srcpad,
- * typically with gst_harness_push or gst_harness_push_from_src.
- *
- * MT safe.
- *
- * Returns: a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no
- * #GstBuffer has been pushed on the #GstHarness srcpad
- *
- * Since: 1.6
- */
-GstClockTime
-gst_harness_get_last_pushed_timestamp (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return priv->last_push_ts;
-}
-
-/**
- * gst_harness_push_event:
- * @h: a #GstHarness
- * @event: a #GstEvent to push
- *
- * Pushes an #GstEvent on the #GstHarness srcpad.
- *
- * MT safe.
- *
- * Returns: a #gboolean with the result from the push
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_push_event (GstHarness * h, GstEvent * event)
-{
- return gst_pad_push_event (h->srcpad, event);
-}
-
-/**
- * gst_harness_pull_event:
- * @h: a #GstHarness
- *
- * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
- * Timeouts after 60 seconds similar to gst_harness_pull.
- *
- * MT safe.
- *
- * Returns: a #GstEvent or %NULL if timed out.
- *
- * Since: 1.6
- */
-GstEvent *
-gst_harness_pull_event (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return (GstEvent *) g_async_queue_timeout_pop (priv->sink_event_queue,
- G_USEC_PER_SEC * 60);
-}
-
-/**
- * gst_harness_try_pull_event:
- * @h: a #GstHarness
- *
- * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
- * See gst_harness_try_pull for details.
- *
- * MT safe.
- *
- * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
- *
- * Since: 1.6
- */
-GstEvent *
-gst_harness_try_pull_event (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return (GstEvent *) g_async_queue_try_pop (priv->sink_event_queue);
-}
-
-/**
- * gst_harness_events_received:
- * @h: a #GstHarness
- *
- * The total number of #GstEvents that has arrived on the #GstHarness sinkpad
- * This number includes events handled by the harness as well as events
- * that have already been pulled out.
- *
- * MT safe.
- *
- * Returns: a #guint number of events received
- *
- * Since: 1.6
- */
-guint
-gst_harness_events_received (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_atomic_int_get (&priv->recv_events);
-}
-
-/**
- * gst_harness_events_in_queue:
- * @h: a #GstHarness
- *
- * The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue
- *
- * MT safe.
- *
- * Returns: a #guint number of events in the queue
- *
- * Since: 1.6
- */
-guint
-gst_harness_events_in_queue (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_async_queue_length (priv->sink_event_queue);
-}
-
-/**
- * gst_harness_push_upstream_event:
- * @h: a #GstHarness
- * @event: a #GstEvent to push
- *
- * Pushes an #GstEvent on the #GstHarness sinkpad.
- *
- * MT safe.
- *
- * Returns: a #gboolean with the result from the push
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_push_upstream_event (GstHarness * h, GstEvent * event)
-{
- g_return_val_if_fail (event != NULL, FALSE);
- g_return_val_if_fail (GST_EVENT_IS_UPSTREAM (event), FALSE);
-
- return gst_pad_push_event (h->sinkpad, event);
-}
-
-/**
- * gst_harness_pull_upstream_event:
- * @h: a #GstHarness
- *
- * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
- * Timeouts after 60 seconds similar to gst_harness_pull.
- *
- * MT safe.
- *
- * Returns: a #GstEvent or %NULL if timed out.
- *
- * Since: 1.6
- */
-GstEvent *
-gst_harness_pull_upstream_event (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return (GstEvent *) g_async_queue_timeout_pop (priv->src_event_queue,
- G_USEC_PER_SEC * 60);
-}
-
-/**
- * gst_harness_try_pull_upstream_event:
- * @h: a #GstHarness
- *
- * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
- * See gst_harness_try_pull for details.
- *
- * MT safe.
- *
- * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
- *
- * Since: 1.6
- */
-GstEvent *
-gst_harness_try_pull_upstream_event (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return (GstEvent *) g_async_queue_try_pop (priv->src_event_queue);
-}
-
-/**
- * gst_harness_upstream_events_received:
- * @h: a #GstHarness
- *
- * The total number of #GstEvents that has arrived on the #GstHarness srcpad
- * This number includes events handled by the harness as well as events
- * that have already been pulled out.
- *
- * MT safe.
- *
- * Returns: a #guint number of events received
- *
- * Since: 1.6
- */
-guint
-gst_harness_upstream_events_received (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_atomic_int_get (&priv->recv_upstream_events);
-}
-
-/**
- * gst_harness_upstream_events_in_queue:
- * @h: a #GstHarness
- *
- * The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue
- *
- * MT safe.
- *
- * Returns: a #guint number of events in the queue
- *
- * Since: 1.6
- */
-guint
-gst_harness_upstream_events_in_queue (GstHarness * h)
-{
- GstHarnessPrivate *priv = h->priv;
- return g_async_queue_length (priv->src_event_queue);
-}
-
-/**
- * gst_harness_query_latency:
- * @h: a #GstHarness
- *
- * Get the min latency reported by any harnessed #GstElement.
- *
- * MT safe.
- *
- * Returns: a #GstClockTime with min latency
- *
- * Since: 1.6
- */
-GstClockTime
-gst_harness_query_latency (GstHarness * h)
-{
- GstQuery *query;
- gboolean is_live;
- GstClockTime min = GST_CLOCK_TIME_NONE;
- GstClockTime max;
-
- query = gst_query_new_latency ();
-
- if (gst_pad_peer_query (h->sinkpad, query)) {
- gst_query_parse_latency (query, &is_live, &min, &max);
- }
- gst_query_unref (query);
-
- return min;
-}
-
-/**
- * gst_harness_set_upstream_latency:
- * @h: a #GstHarness
- * @latency: a #GstClockTime specifying the latency
- *
- * Sets the min latency reported by #GstHarness when receiving a latency-query
- *
- * Since: 1.6
- */
-void
-gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency)
-{
- g_return_if_fail (GST_CLOCK_TIME_IS_VALID (latency));
-
- h->priv->latency_min = latency;
-}
-
-/**
- * gst_harness_set_live:
- * @h: a #GstHarness
- * @is_live: %TRUE for live, %FALSE for non-live
- *
- * Sets the liveness reported by #GstHarness when receiving a latency-query.
- * The default is %TRUE.
- *
- * Since: 1.20
- */
-void
-gst_harness_set_live (GstHarness * h, gboolean is_live)
-{
- GstHarnessPrivate *priv = h->priv;
- priv->is_live = is_live;
-}
-
-/**
- * gst_harness_get_allocator:
- * @h: a #GstHarness
- * @allocator: (out) (allow-none) (transfer none): the #GstAllocator used
- * @params: (out) (allow-none) (transfer full): the #GstAllocationParams of
- * @allocator
- *
- * Gets the @allocator and its @params that has been decided to use after an
- * allocation query.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_get_allocator (GstHarness * h, GstAllocator ** allocator,
- GstAllocationParams * params)
-{
- GstHarnessPrivate *priv = h->priv;
- if (allocator)
- *allocator = priv->allocator;
- if (params)
- *params = priv->allocation_params;
-}
-
-
-/**
- * gst_harness_set_propose_allocator:
- * @h: a #GstHarness
- * @allocator: (allow-none) (transfer full): a #GstAllocator
- * @params: (allow-none) (transfer none): a #GstAllocationParams
- *
- * Sets the @allocator and @params to propose when receiving an allocation
- * query.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set_propose_allocator (GstHarness * h, GstAllocator * allocator,
- const GstAllocationParams * params)
-{
- GstHarnessPrivate *priv = h->priv;
- if (allocator)
- priv->propose_allocator = allocator;
- if (params)
- priv->propose_allocation_params = *params;
-}
-
-/**
- * gst_harness_add_propose_allocation_meta:
- * @h: a #GstHarness
- * @api: a metadata API
- * @params: (allow-none) (transfer none): API specific parameters
- *
- * Add api with params as one of the supported metadata API to propose when
- * receiving an allocation query.
- *
- * MT safe.
- *
- * Since: 1.16
- */
-void
-gst_harness_add_propose_allocation_meta (GstHarness * h, GType api,
- const GstStructure * params)
-{
- GstHarnessPrivate *priv = h->priv;
- ProposeMeta meta;
-
- meta.api = api;
- meta.params = params ? gst_structure_copy (params) : NULL;
-
- if (!priv->propose_allocation_metas) {
- priv->propose_allocation_metas =
- g_array_new (FALSE, FALSE, sizeof (ProposeMeta));
- g_array_set_clear_func (priv->propose_allocation_metas,
- (GDestroyNotify) propose_meta_clear);
- }
- g_array_append_val (priv->propose_allocation_metas, meta);
-}
-
-/**
- * gst_harness_add_src_harness:
- * @h: a #GstHarness
- * @src_harness: (transfer full): a #GstHarness to be added as a src-harness.
- * @has_clock_wait: a #gboolean specifying if the #GstElement uses
- * gst_clock_wait_id internally.
- *
- * A src-harness is a great way of providing the #GstHarness with data.
- * By adding a src-type #GstElement, it is then easy to use functions like
- * gst_harness_push_from_src or gst_harness_src_crank_and_push_many
- * to provide your harnessed element with input. The @has_clock_wait variable
- * is a great way to control you src-element with, in that you can have it
- * produce a buffer for you by simply cranking the clock, and not have it
- * spin out of control producing buffers as fast as possible.
- *
- * If a src-harness already exists it will be replaced.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_src_harness (GstHarness * h,
- GstHarness * src_harness, gboolean has_clock_wait)
-{
- if (h->src_harness)
- gst_harness_teardown (h->src_harness);
- h->src_harness = src_harness;
-
- HARNESS_LOCK (h->src_harness);
- gst_harness_set_forward_pad (h->src_harness, h->srcpad);
- HARNESS_UNLOCK (h->src_harness);
-
- h->src_harness->priv->has_clock_wait = has_clock_wait;
- gst_harness_set_forwarding (h->src_harness, h->priv->forwarding);
-}
-
-/**
- * gst_harness_add_src:
- * @h: a #GstHarness
- * @src_element_name: a #gchar with the name of a #GstElement
- * @has_clock_wait: a #gboolean specifying if the #GstElement uses
- * gst_clock_wait_id internally.
- *
- * Similar to gst_harness_add_src_harness, this is a convenience to
- * directly create a src-harness using the @src_element_name name specified.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_src (GstHarness * h,
- const gchar * src_element_name, gboolean has_clock_wait)
-{
- GstHarness *src_harness = gst_harness_new (src_element_name);
- gst_harness_add_src_harness (h, src_harness, has_clock_wait);
-}
-
-/**
- * gst_harness_add_src_parse:
- * @h: a #GstHarness
- * @launchline: a #gchar describing a gst-launch type line
- * @has_clock_wait: a #gboolean specifying if the #GstElement uses
- * gst_clock_wait_id internally.
- *
- * Similar to gst_harness_add_src, this allows you to specify a launch-line,
- * which can be useful for both having more then one #GstElement acting as your
- * src (Like a src producing raw buffers, and then an encoder, providing encoded
- * data), but also by allowing you to set properties like "is-live" directly on
- * the elements.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_src_parse (GstHarness * h,
- const gchar * launchline, gboolean has_clock_wait)
-{
- GstHarness *src_harness = gst_harness_new_parse (launchline);
- gst_harness_add_src_harness (h, src_harness, has_clock_wait);
-}
-
-/**
- * gst_harness_push_from_src:
- * @h: a #GstHarness
- *
- * Transfer data from the src-#GstHarness to the main-#GstHarness. It consists
- * of 4 steps:
- * 1: Make sure the src is started. (see: gst_harness_play)
- * 2: Crank the clock (see: gst_harness_crank_single_clock_wait)
- * 3: Pull a #GstBuffer from the src-#GstHarness (see: gst_harness_pull)
- * 4: Push the same #GstBuffer into the main-#GstHarness (see: gst_harness_push)
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn with the result of the push
- *
- * Since: 1.6
- */
-GstFlowReturn
-gst_harness_push_from_src (GstHarness * h)
-{
- GstBuffer *buf;
- gboolean crank;
-
- g_assert (h->src_harness);
-
- /* FIXME: this *is* the right time to start the src,
- but maybe a flag so we don't keep telling it to play? */
- gst_harness_play (h->src_harness);
-
- if (h->src_harness->priv->has_clock_wait) {
- crank = gst_harness_crank_single_clock_wait (h->src_harness);
- g_assert (crank);
- }
-
- buf = gst_harness_pull (h->src_harness);
- g_assert (buf != NULL);
- return gst_harness_push (h, buf);
-}
-
-/**
- * gst_harness_src_crank_and_push_many:
- * @h: a #GstHarness
- * @cranks: a #gint with the number of calls to gst_harness_crank_single_clock_wait
- * @pushes: a #gint with the number of calls to gst_harness_push
- *
- * Transfer data from the src-#GstHarness to the main-#GstHarness. Similar to
- * gst_harness_push_from_src, this variant allows you to specify how many cranks
- * and how many pushes to perform. This can be useful for both moving a lot
- * of data at the same time, as well as cases when one crank does not equal one
- * buffer to push and v.v.
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn with the result of the push
- *
- * Since: 1.6
- */
-GstFlowReturn
-gst_harness_src_crank_and_push_many (GstHarness * h, gint cranks, gint pushes)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- gboolean crank;
- int i;
-
- g_assert (h->src_harness);
- gst_harness_play (h->src_harness);
-
- for (i = 0; i < cranks; i++) {
- crank = gst_harness_crank_single_clock_wait (h->src_harness);
- g_assert (crank);
- }
-
- for (i = 0; i < pushes; i++) {
- GstBuffer *buf;
- buf = gst_harness_pull (h->src_harness);
- g_assert (buf != NULL);
- ret = gst_harness_push (h, buf);
- if (ret != GST_FLOW_OK)
- break;
- }
-
- return ret;
-}
-
-/**
- * gst_harness_src_push_event:
- * @h: a #GstHarness
- *
- * Similar to what gst_harness_src_push does with #GstBuffers, this transfers
- * a #GstEvent from the src-#GstHarness to the main-#GstHarness. Note that
- * some #GstEvents are being transferred automagically. Look at sink_forward_pad
- * for details.
- *
- * MT safe.
- *
- * Returns: a #gboolean with the result of the push
- *
- * Since: 1.6
- */
-gboolean
-gst_harness_src_push_event (GstHarness * h)
-{
- return gst_harness_push_event (h, gst_harness_pull_event (h->src_harness));
-}
-
-
-static gboolean
-forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
-{
- GstPad *fwdpad = user_data;
- return gst_pad_push_event (fwdpad, gst_event_ref (*ev));
-}
-
-/**
- * gst_harness_add_sink_harness:
- * @h: a #GstHarness
- * @sink_harness: (transfer full): a #GstHarness to be added as a sink-harness.
- *
- * Similar to gst_harness_add_src, this allows you to send the data coming out
- * of your harnessed #GstElement to a sink-element, allowing to test different
- * responses the element output might create in sink elements. An example might
- * be an existing sink providing some analytical data on the input it receives that
- * can be useful to your testing. If the goal is to test a sink-element itself,
- * this is better achieved using gst_harness_new directly on the sink.
- *
- * If a sink-harness already exists it will be replaced.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness)
-{
- GstHarnessPrivate *priv;
- GstPad *fwdpad;
-
- HARNESS_LOCK (h);
- priv = h->priv;
-
- if (h->sink_harness) {
- gst_harness_set_forward_pad (h, NULL);
- gst_harness_teardown (h->sink_harness);
- }
- h->sink_harness = sink_harness;
-
- fwdpad = h->sink_harness->srcpad;
- if (fwdpad)
- gst_object_ref (fwdpad);
-
- if (priv->forwarding && h->sinkpad && fwdpad) {
- HARNESS_UNLOCK (h);
- gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, fwdpad);
- HARNESS_LOCK (h);
- }
-
- gst_harness_set_forward_pad (h, fwdpad);
- if (fwdpad)
- gst_object_unref (fwdpad);
-
- gst_harness_set_forwarding (h->sink_harness, priv->forwarding);
-
- HARNESS_UNLOCK (h);
-}
-
-/**
- * gst_harness_add_sink:
- * @h: a #GstHarness
- * @sink_element_name: a #gchar with the name of a #GstElement
- *
- * Similar to gst_harness_add_sink_harness, this is a convenience to
- * directly create a sink-harness using the @sink_element_name name specified.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_sink (GstHarness * h, const gchar * sink_element_name)
-{
- GstHarness *sink_harness = gst_harness_new (sink_element_name);
- gst_harness_add_sink_harness (h, sink_harness);
-}
-
-/**
- * gst_harness_add_sink_parse:
- * @h: a #GstHarness
- * @launchline: a #gchar with the name of a #GstElement
- *
- * Similar to gst_harness_add_sink, this allows you to specify a launch-line
- * instead of just an element name. See gst_harness_add_src_parse for details.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_sink_parse (GstHarness * h, const gchar * launchline)
-{
- GstHarness *sink_harness = gst_harness_new_parse (launchline);
- gst_harness_add_sink_harness (h, sink_harness);
-}
-
-/**
- * gst_harness_push_to_sink:
- * @h: a #GstHarness
- *
- * Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness.
- * See gst_harness_push_from_src for details.
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn with the result of the push
- *
- * Since: 1.6
- */
-GstFlowReturn
-gst_harness_push_to_sink (GstHarness * h)
-{
- GstBuffer *buf;
- g_assert (h->sink_harness);
- buf = gst_harness_pull (h);
- g_assert (buf != NULL);
- return gst_harness_push (h->sink_harness, buf);
-}
-
-/**
- * gst_harness_sink_push_many:
- * @h: a #GstHarness
- * @pushes: a #gint with the number of calls to gst_harness_push_to_sink
- *
- * Convenience that calls gst_harness_push_to_sink @pushes number of times.
- * Will abort the pushing if any one push fails.
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn with the result of the push
- *
- * Since: 1.6
- */
-GstFlowReturn
-gst_harness_sink_push_many (GstHarness * h, gint pushes)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- int i;
- g_assert (h->sink_harness);
- for (i = 0; i < pushes; i++) {
- ret = gst_harness_push_to_sink (h);
- if (ret != GST_FLOW_OK)
- break;
- }
- return ret;
-}
-
-/**
- * gst_harness_find_element:
- * @h: a #GstHarness
- * @element_name: a #gchar with a #GstElementFactory name
- *
- * Most useful in conjunction with gst_harness_new_parse, this will scan the
- * #GstElements inside the #GstHarness, and check if any of them matches
- * @element_name. Typical usecase being that you need to access one of the
- * harnessed elements for properties and/or signals.
- *
- * MT safe.
- *
- * Returns: (transfer full) (allow-none): a #GstElement or %NULL if not found
- *
- * Since: 1.6
- */
-GstElement *
-gst_harness_find_element (GstHarness * h, const gchar * element_name)
-{
- gboolean done = FALSE;
- GstIterator *iter;
- GValue data = G_VALUE_INIT;
-
- if (!GST_IS_BIN (h->element)) {
- GstPluginFeature *feature;
-
- g_return_val_if_fail (GST_IS_ELEMENT (h->element), NULL);
-
- feature = GST_PLUGIN_FEATURE (gst_element_get_factory (h->element));
- if (!strcmp (element_name, gst_plugin_feature_get_name (feature)))
- return gst_object_ref (h->element);
-
- return NULL;
- }
-
- iter = gst_bin_iterate_elements (GST_BIN (h->element));
- done = FALSE;
-
- while (!done) {
- switch (gst_iterator_next (iter, &data)) {
- case GST_ITERATOR_OK:
- {
- GstElement *element = g_value_get_object (&data);
- GstPluginFeature *feature =
- GST_PLUGIN_FEATURE (gst_element_get_factory (element));
- if (!strcmp (element_name, gst_plugin_feature_get_name (feature))) {
- gst_iterator_free (iter);
- return element;
- }
- g_value_reset (&data);
- break;
- }
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- }
- }
- gst_iterator_free (iter);
-
- return NULL;
-}
-
-/**
- * gst_harness_set:
- * @h: a #GstHarness
- * @element_name: a #gchar with a #GstElementFactory name
- * @first_property_name: a #gchar with the first property name
- * @...: value for the first property, followed optionally by more
- * name/value pairs, followed by %NULL
- *
- * A convenience function to allows you to call g_object_set on a #GstElement
- * that are residing inside the #GstHarness, by using normal g_object_set
- * syntax.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_set (GstHarness * h,
- const gchar * element_name, const gchar * first_property_name, ...)
-{
- va_list var_args;
- GstElement *element = gst_harness_find_element (h, element_name);
- va_start (var_args, first_property_name);
- g_object_set_valist (G_OBJECT (element), first_property_name, var_args);
- va_end (var_args);
- gst_object_unref (element);
-}
-
-/**
- * gst_harness_get:
- * @h: a #GstHarness
- * @element_name: a #gchar with a #GstElementFactory name
- * @first_property_name: a #gchar with the first property name
- * @...: return location for the first property, followed optionally by more
- * name/return location pairs, followed by %NULL
- *
- * A convenience function to allows you to call g_object_get on a #GstElement
- * that are residing inside the #GstHarness, by using normal g_object_get
- * syntax.
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_get (GstHarness * h,
- const gchar * element_name, const gchar * first_property_name, ...)
-{
- va_list var_args;
- GstElement *element = gst_harness_find_element (h, element_name);
- va_start (var_args, first_property_name);
- g_object_get_valist (G_OBJECT (element), first_property_name, var_args);
- va_end (var_args);
- gst_object_unref (element);
-}
-
-/**
- * gst_harness_add_probe:
- * @h: a #GstHarness
- * @element_name: a #gchar with a #GstElementFactory name
- * @pad_name: a #gchar with the name of the pad to attach the probe to
- * @mask: a #GstPadProbeType (see gst_pad_add_probe)
- * @callback: a #GstPadProbeCallback (see gst_pad_add_probe)
- * @user_data: a #gpointer (see gst_pad_add_probe)
- * @destroy_data: a #GDestroyNotify (see gst_pad_add_probe)
- *
- * A convenience function to allows you to call gst_pad_add_probe on a
- * #GstPad of a #GstElement that are residing inside the #GstHarness,
- * by using normal gst_pad_add_probe syntax
- *
- * MT safe.
- *
- * Since: 1.6
- */
-void
-gst_harness_add_probe (GstHarness * h,
- const gchar * element_name, const gchar * pad_name, GstPadProbeType mask,
- GstPadProbeCallback callback, gpointer user_data,
- GDestroyNotify destroy_data)
-{
- GstElement *element = gst_harness_find_element (h, element_name);
- GstPad *pad = gst_element_get_static_pad (element, pad_name);
- gst_pad_add_probe (pad, mask, callback, user_data, destroy_data);
- gst_object_unref (pad);
- gst_object_unref (element);
-}
-
-/******************************************************************************/
-/* STRESS */
-/******************************************************************************/
-struct _GstHarnessThread
-{
- GstHarness *h;
- GThread *thread;
- gboolean running;
-
- gulong sleep;
-
- GDestroyNotify freefunc;
-};
-
-typedef struct
-{
- GstHarnessThread t;
-
- GFunc init;
- GFunc callback;
- gpointer data;
-} GstHarnessCustomThread;
-
-typedef struct
-{
- GstHarnessThread t;
-
- GstCaps *caps;
- GstSegment segment;
- GstHarnessPrepareBufferFunc func;
- gpointer data;
- GDestroyNotify notify;
-} GstHarnessPushBufferThread;
-
-typedef struct
-{
- GstHarnessThread t;
-
- GstHarnessPrepareEventFunc func;
- gpointer data;
- GDestroyNotify notify;
-} GstHarnessPushEventThread;
-
-typedef struct
-{
- GstHarnessThread t;
-
- gchar *name;
- GValue value;
-} GstHarnessPropThread;
-
-typedef struct
-{
- GstHarnessThread t;
-
- GstPadTemplate *templ;
- gchar *name;
- GstCaps *caps;
- gboolean release;
-
- GSList *pads;
-} GstHarnessReqPadThread;
-
-static void
-gst_harness_thread_init (GstHarnessThread * t, GDestroyNotify freefunc,
- GstHarness * h, gulong sleep)
-{
- t->freefunc = freefunc;
- t->h = h;
- t->sleep = sleep;
-
- g_ptr_array_add (h->priv->stress, t);
-}
-
-static void
-gst_harness_thread_free (GstHarnessThread * t)
-{
- g_slice_free (GstHarnessThread, t);
-}
-
-static void
-gst_harness_custom_thread_free (GstHarnessCustomThread * t)
-{
- g_slice_free (GstHarnessCustomThread, t);
-}
-
-static void
-gst_harness_push_buffer_thread_free (GstHarnessPushBufferThread * t)
-{
- if (t != NULL) {
- gst_caps_replace (&t->caps, NULL);
- if (t->notify != NULL)
- t->notify (t->data);
- g_slice_free (GstHarnessPushBufferThread, t);
- }
-}
-
-static void
-gst_harness_push_event_thread_free (GstHarnessPushEventThread * t)
-{
- if (t != NULL) {
- if (t->notify != NULL)
- t->notify (t->data);
- g_slice_free (GstHarnessPushEventThread, t);
- }
-}
-
-static void
-gst_harness_property_thread_free (GstHarnessPropThread * t)
-{
- if (t != NULL) {
- g_free (t->name);
- g_value_unset (&t->value);
- g_slice_free (GstHarnessPropThread, t);
- }
-}
-
-static void
-gst_harness_requestpad_release (GstPad * pad, GstElement * element)
-{
- gst_element_release_request_pad (element, pad);
- gst_object_unref (pad);
-}
-
-static void
-gst_harness_requestpad_release_pads (GstHarnessReqPadThread * rpt)
-{
- g_slist_foreach (rpt->pads, (GFunc) gst_harness_requestpad_release,
- rpt->t.h->element);
- g_slist_free (rpt->pads);
- rpt->pads = NULL;
-}
-
-static void
-gst_harness_requestpad_thread_free (GstHarnessReqPadThread * t)
-{
- if (t != NULL) {
- gst_object_replace ((GstObject **) & t->templ, NULL);
- g_free (t->name);
- gst_caps_replace (&t->caps, NULL);
-
- gst_harness_requestpad_release_pads (t);
- g_slice_free (GstHarnessReqPadThread, t);
- }
-}
-
-#define GST_HARNESS_THREAD_START(ID, t) \
- (((GstHarnessThread *)t)->running = TRUE, \
- ((GstHarnessThread *)t)->thread = g_thread_new ( \
- "gst-harness-stress-"G_STRINGIFY(ID), \
- (GThreadFunc)gst_harness_stress_##ID##_func, t))
-#define GST_HARNESS_THREAD_END(t) \
- (t->running = FALSE, \
- GPOINTER_TO_UINT (g_thread_join (t->thread)))
-
-static void
-gst_harness_stress_free (GstHarnessThread * t)
-{
- if (t != NULL && t->freefunc != NULL)
- t->freefunc (t);
-}
-
-static gpointer
-gst_harness_stress_custom_func (GstHarnessThread * t)
-{
- GstHarnessCustomThread *ct = (GstHarnessCustomThread *) t;
- guint count = 0;
-
- if (ct->init != NULL)
- ct->init (ct, ct->data);
-
- while (t->running) {
- ct->callback (ct, ct->data);
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-
-static gpointer
-gst_harness_stress_statechange_func (GstHarnessThread * t)
-{
- guint count = 0;
-
- while (t->running) {
- GstClock *clock = gst_element_get_clock (t->h->element);
- GstIterator *it;
- gboolean done = FALSE;
- gboolean change;
-
- change = gst_element_set_state (t->h->element, GST_STATE_NULL);
- g_assert (change == GST_STATE_CHANGE_SUCCESS);
- g_thread_yield ();
-
- it = gst_element_iterate_sink_pads (t->h->element);
- while (!done) {
- GValue item = G_VALUE_INIT;
- switch (gst_iterator_next (it, &item)) {
- case GST_ITERATOR_OK:
- {
- GstPad *sinkpad = g_value_get_object (&item);
- GstPad *srcpad = gst_pad_get_peer (sinkpad);
- if (srcpad != NULL) {
- gst_pad_unlink (srcpad, sinkpad);
- gst_pad_link (srcpad, sinkpad);
- gst_object_unref (srcpad);
- }
- g_value_reset (&item);
- break;
- }
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (it);
- break;
- case GST_ITERATOR_ERROR:
- g_assert_not_reached ();
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- }
- g_value_unset (&item);
- }
- gst_iterator_free (it);
-
- if (clock != NULL) {
- gst_element_set_clock (t->h->element, clock);
- gst_object_unref (clock);
- }
- change = gst_element_set_state (t->h->element, GST_STATE_PLAYING);
- g_assert (change == GST_STATE_CHANGE_SUCCESS);
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-static gpointer
-gst_harness_stress_buffer_func (GstHarnessThread * t)
-{
- GstHarnessPushBufferThread *pt = (GstHarnessPushBufferThread *) t;
- guint count = 0;
- gchar *sid;
- gboolean handled;
-
- /* Push stream start, caps and segment events */
- sid = g_strdup_printf ("%s-%p", GST_OBJECT_NAME (t->h->element), t->h);
- handled = gst_pad_push_event (t->h->srcpad, gst_event_new_stream_start (sid));
- g_assert (handled);
- g_free (sid);
- handled = gst_pad_push_event (t->h->srcpad, gst_event_new_caps (pt->caps));
- g_assert (handled);
- handled = gst_pad_push_event (t->h->srcpad,
- gst_event_new_segment (&pt->segment));
- g_assert (handled);
-
- while (t->running) {
- gst_harness_push (t->h, pt->func (t->h, pt->data));
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-static gpointer
-gst_harness_stress_event_func (GstHarnessThread * t)
-{
- GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
- guint count = 0;
-
- while (t->running) {
- gst_harness_push_event (t->h, pet->func (t->h, pet->data));
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-static gpointer
-gst_harness_stress_upstream_event_func (GstHarnessThread * t)
-{
- GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
- guint count = 0;
-
- while (t->running) {
- gst_harness_push_upstream_event (t->h, pet->func (t->h, pet->data));
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-static gpointer
-gst_harness_stress_property_func (GstHarnessThread * t)
-{
- GstHarnessPropThread *pt = (GstHarnessPropThread *) t;
- guint count = 0;
-
- while (t->running) {
- GValue value = G_VALUE_INIT;
-
- g_object_set_property (G_OBJECT (t->h->element), pt->name, &pt->value);
-
- g_value_init (&value, G_VALUE_TYPE (&pt->value));
- g_object_get_property (G_OBJECT (t->h->element), pt->name, &value);
- g_value_reset (&value);
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-static gpointer
-gst_harness_stress_requestpad_func (GstHarnessThread * t)
-{
- GstHarnessReqPadThread *rpt = (GstHarnessReqPadThread *) t;
- guint count = 0;
-
- while (t->running) {
- GstPad *reqpad;
-
- if (rpt->release)
- gst_harness_requestpad_release_pads (rpt);
-
- g_thread_yield ();
-
- reqpad = gst_element_request_pad (t->h->element,
- rpt->templ, rpt->name, rpt->caps);
-
- g_assert (reqpad != NULL);
-
- rpt->pads = g_slist_prepend (rpt->pads, reqpad);
-
- count++;
- g_usleep (t->sleep);
- }
- return GUINT_TO_POINTER (count);
-}
-
-/**
- * gst_harness_stress_thread_stop:
- * @t: a #GstHarnessThread
- *
- * Stop the running #GstHarnessThread
- *
- * MT safe.
- *
- * Since: 1.6
- */
-guint
-gst_harness_stress_thread_stop (GstHarnessThread * t)
-{
- guint ret;
-
- g_return_val_if_fail (t != NULL, 0);
-
- ret = GST_HARNESS_THREAD_END (t);
- g_ptr_array_remove (t->h->priv->stress, t);
- return ret;
-}
-
-/**
- * gst_harness_stress_custom_start: (skip)
- * @h: a #GstHarness
- * @init: (allow-none): a #GFunc that is called initially and only once
- * @callback: a #GFunc that is called as often as possible
- * @data: a #gpointer with custom data to pass to the @callback function
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each call to the @callback
- *
- * Start a custom stress-thread that will call your @callback for every
- * iteration allowing you to do something nasty.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_custom_start (GstHarness * h,
- GFunc init, GFunc callback, gpointer data, gulong sleep)
-{
- GstHarnessCustomThread *t = g_slice_new0 (GstHarnessCustomThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_custom_thread_free, h, sleep);
-
- t->init = init;
- t->callback = callback;
- t->data = data;
-
- GST_HARNESS_THREAD_START (custom, t);
- return &t->t;
-}
-
-/**
- * gst_harness_stress_statechange_start_full: (skip)
- * @h: a #GstHarness
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each state-change
- *
- * Change the state of your harnessed #GstElement from NULL to PLAYING and
- * back again, only pausing for @sleep microseconds every time.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_statechange_start_full (GstHarness * h, gulong sleep)
-{
- GstHarnessThread *t = g_slice_new0 (GstHarnessThread);
- gst_harness_thread_init (t,
- (GDestroyNotify) gst_harness_thread_free, h, sleep);
- GST_HARNESS_THREAD_START (statechange, t);
- return t;
-}
-
-static GstBuffer *
-gst_harness_ref_buffer (GstHarness * h, gpointer data)
-{
- (void) h;
- return gst_buffer_ref (GST_BUFFER_CAST (data));
-}
-
-static GstEvent *
-gst_harness_ref_event (GstHarness * h, gpointer data)
-{
- (void) h;
- return gst_event_ref (GST_EVENT_CAST (data));
-}
-
-/**
- * gst_harness_stress_push_buffer_start_full: (skip)
- * @h: a #GstHarness
- * @caps: a #GstCaps for the #GstBuffer
- * @segment: a #GstSegment
- * @buf: a #GstBuffer to push
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each call to gst_pad_push
- *
- * Push a #GstBuffer in intervals of @sleep microseconds.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_push_buffer_start_full (GstHarness * h,
- GstCaps * caps, const GstSegment * segment, GstBuffer * buf, gulong sleep)
-{
- return gst_harness_stress_push_buffer_with_cb_start_full (h, caps, segment,
- gst_harness_ref_buffer, gst_buffer_ref (buf),
- (GDestroyNotify) gst_buffer_unref, sleep);
-}
-
-/**
- * gst_harness_stress_push_buffer_with_cb_start_full: (skip)
- * @h: a #GstHarness
- * @caps: a #GstCaps for the #GstBuffer
- * @segment: a #GstSegment
- * @func: a #GstHarnessPrepareBufferFunc function called before every iteration
- * to prepare / create a #GstBuffer for pushing
- * @data: a #gpointer with data to the #GstHarnessPrepareBufferFunc function
- * @notify: a #GDestroyNotify that is called when thread is stopped
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each call to gst_pad_push
- *
- * Push a #GstBuffer returned by @func in intervals of @sleep microseconds.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h,
- GstCaps * caps, const GstSegment * segment,
- GstHarnessPrepareBufferFunc func, gpointer data, GDestroyNotify notify,
- gulong sleep)
-{
- GstHarnessPushBufferThread *t = g_slice_new0 (GstHarnessPushBufferThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_push_buffer_thread_free, h, sleep);
-
- gst_caps_replace (&t->caps, caps);
- t->segment = *segment;
- t->func = func;
- t->data = data;
- t->notify = notify;
-
- GST_HARNESS_THREAD_START (buffer, t);
- return &t->t;
-}
-
-/**
- * gst_harness_stress_push_event_start_full: (skip)
- * @h: a #GstHarness
- * @event: a #GstEvent to push
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each gst_event_push with @event
- *
- * Push the @event onto the harnessed #GstElement sinkpad in intervals of
- * @sleep microseconds
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_push_event_start_full (GstHarness * h,
- GstEvent * event, gulong sleep)
-{
- return gst_harness_stress_push_event_with_cb_start_full (h,
- gst_harness_ref_event, gst_event_ref (event),
- (GDestroyNotify) gst_event_unref, sleep);
-}
-
-/**
- * gst_harness_stress_push_event_with_cb_start_full: (skip)
- * @h: a #GstHarness
- * @func: a #GstHarnessPrepareEventFunc function called before every iteration
- * to prepare / create a #GstEvent for pushing
- * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
- * @notify: a #GDestroyNotify that is called when thread is stopped
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each call to gst_pad_push
- *
- * Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad
- * in intervals of @sleep microseconds.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.8
- */
-GstHarnessThread *
-gst_harness_stress_push_event_with_cb_start_full (GstHarness * h,
- GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
- gulong sleep)
-{
- GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
-
- t->func = func;
- t->data = data;
- t->notify = notify;
-
- GST_HARNESS_THREAD_START (event, t);
- return &t->t;
-}
-
-/**
- * gst_harness_stress_push_upstream_event_start_full: (skip)
- * @h: a #GstHarness
- * @event: a #GstEvent to push
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each gst_event_push with @event
- *
- * Push the @event onto the harnessed #GstElement srcpad in intervals of
- * @sleep microseconds.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_push_upstream_event_start_full (GstHarness * h,
- GstEvent * event, gulong sleep)
-{
- return gst_harness_stress_push_upstream_event_with_cb_start_full (h,
- gst_harness_ref_event, gst_event_ref (event),
- (GDestroyNotify) gst_event_unref, sleep);
-}
-
-/**
- * gst_harness_stress_push_upstream_event_with_cb_start_full: (skip)
- * @h: a #GstHarness
- * @func: a #GstHarnessPrepareEventFunc function called before every iteration
- * to prepare / create a #GstEvent for pushing
- * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
- * @notify: a #GDestroyNotify that is called when thread is stopped
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each call to gst_pad_push
- *
- * Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad
- * in intervals of @sleep microseconds.
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.8
- */
-GstHarnessThread *
-gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h,
- GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
- gulong sleep)
-{
- GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
-
- t->func = func;
- t->data = data;
- t->notify = notify;
-
- GST_HARNESS_THREAD_START (upstream_event, t);
- return &t->t;
-}
-
-/**
- * gst_harness_stress_property_start_full: (skip)
- * @h: a #GstHarness
- * @name: a #gchar specifying a property name
- * @value: a #GValue to set the property to
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each g_object_set with @name and @value
- *
- * Call g_object_set with @name and @value in intervals of @sleep microseconds
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_property_start_full (GstHarness * h,
- const gchar * name, const GValue * value, gulong sleep)
-{
- GstHarnessPropThread *t = g_slice_new0 (GstHarnessPropThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_property_thread_free, h, sleep);
-
- t->name = g_strdup (name);
- g_value_init (&t->value, G_VALUE_TYPE (value));
- g_value_copy (value, &t->value);
-
- GST_HARNESS_THREAD_START (property, t);
- return &t->t;
-}
-
-/**
- * gst_harness_stress_requestpad_start_full: (skip)
- * @h: a #GstHarness
- * @templ: a #GstPadTemplate
- * @name: a #gchar
- * @caps: a #GstCaps
- * @release: a #gboolean
- * @sleep: a #gulong specifying how long to sleep in (microseconds) for
- * each gst_element_request_pad
- *
- * Call gst_element_request_pad in intervals of @sleep microseconds
- *
- * MT safe.
- *
- * Returns: a #GstHarnessThread
- *
- * Since: 1.6
- */
-GstHarnessThread *
-gst_harness_stress_requestpad_start_full (GstHarness * h,
- GstPadTemplate * templ, const gchar * name, GstCaps * caps,
- gboolean release, gulong sleep)
-{
- GstHarnessReqPadThread *t = g_slice_new0 (GstHarnessReqPadThread);
- gst_harness_thread_init (&t->t,
- (GDestroyNotify) gst_harness_requestpad_thread_free, h, sleep);
-
- t->templ = gst_object_ref (templ);
- t->name = g_strdup (name);
- gst_caps_replace (&t->caps, caps);
- t->release = release;
-
- GST_HARNESS_THREAD_START (requestpad, t);
- return &t->t;
-}
diff --git a/libs/gst/check/gstharness.h b/libs/gst/check/gstharness.h
deleted file mode 100644
index 160fdb01d8..0000000000
--- a/libs/gst/check/gstharness.h
+++ /dev/null
@@ -1,474 +0,0 @@
-/* GstHarness - A test-harness for GStreamer testing
- *
- * Copyright (C) 2012-2015 Pexip <pexip.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_HARNESS_H__
-#define __GST_HARNESS_H__
-
-#include <gst/gst.h>
-#include <gst/check/gsttestclock.h>
-#include <gst/check/check-prelude.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstHarnessThread:
- *
- * Opaque handle representing a GstHarness stress testing thread.
- *
- * Since: 1.6
- */
-typedef struct _GstHarnessThread GstHarnessThread;
-
-typedef struct _GstHarness GstHarness;
-typedef struct _GstHarnessPrivate GstHarnessPrivate;
-
-/**
- * GstHarness:
- * @element: the element inside the harness
- * @srcpad: the internal harness source pad
- * @sinkpad: the internal harness sink pad
- * @src_harness: the source (input) harness (if any)
- * @sink_harness: the sink (output) harness (if any)
- *
- * Since: 1.6
- */
-struct _GstHarness {
- GstElement * element;
-
- GstPad * srcpad;
- GstPad * sinkpad;
-
- GstHarness * src_harness;
- GstHarness * sink_harness;
-
- /*< private >*/
- GstHarnessPrivate * priv;
-};
-
-/* Harness creation */
-
-GST_CHECK_API
-GstHarness * gst_harness_new_empty (void);
-
-GST_CHECK_API
-void gst_harness_add_element_full (GstHarness * h,
- GstElement * element,
- GstStaticPadTemplate * hsrc,
- const gchar * element_sinkpad_name,
- GstStaticPadTemplate * hsink,
- const gchar * element_srcpad_name);
-
-GST_CHECK_API
-GstHarness * gst_harness_new_full (GstElement * element,
- GstStaticPadTemplate * hsrc,
- const gchar * element_sinkpad_name,
- GstStaticPadTemplate * hsink,
- const gchar * element_srcpad_name);
-
-GST_CHECK_API
-GstHarness * gst_harness_new_with_element (GstElement * element,
- const gchar * element_sinkpad_name,
- const gchar * element_srcpad_name);
-
-GST_CHECK_API
-GstHarness * gst_harness_new_with_padnames (const gchar * element_name,
- const gchar * element_sinkpad_name,
- const gchar * element_srcpad_name);
-
-GST_CHECK_API
-GstHarness * gst_harness_new_with_templates (const gchar * element_name,
- GstStaticPadTemplate * hsrc,
- GstStaticPadTemplate * hsink);
-
-GST_CHECK_API
-GstHarness * gst_harness_new (const gchar * element_name);
-
-GST_CHECK_API
-GstHarness * gst_harness_new_parse (const gchar * launchline);
-
-GST_CHECK_API
-void gst_harness_add_parse (GstHarness * h, const gchar * launchline);
-
-GST_CHECK_API
-void gst_harness_teardown (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad);
-
-GST_CHECK_API
-void gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad);
-
-/* Caps Functions */
-
-GST_CHECK_API
-void gst_harness_set_src_caps (GstHarness * h, GstCaps * caps);
-
-GST_CHECK_API
-void gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps);
-
-GST_CHECK_API
-void gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out);
-
-GST_CHECK_API
-void gst_harness_set_src_caps_str (GstHarness * h, const gchar * str);
-
-GST_CHECK_API
-void gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str);
-
-GST_CHECK_API
-void gst_harness_set_caps_str (GstHarness * h,
- const gchar * in,
- const gchar * out);
-
-/* Clock Functions */
-
-GST_CHECK_API
-void gst_harness_use_systemclock (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_use_testclock (GstHarness * h);
-
-GST_CHECK_API
-GstTestClock * gst_harness_get_testclock (GstHarness * h);
-
-GST_CHECK_API
-gboolean gst_harness_set_time (GstHarness * h, GstClockTime time);
-
-GST_CHECK_API
-gboolean gst_harness_wait_for_clock_id_waits (GstHarness * h,
- guint waits,
- guint timeout);
-
-GST_CHECK_API
-gboolean gst_harness_crank_single_clock_wait (GstHarness * h);
-
-GST_CHECK_API
-gboolean gst_harness_crank_multiple_clock_waits (GstHarness * h,
- guint waits);
-
-/* misc */
-
-GST_CHECK_API
-void gst_harness_play (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_set_blocking_push_mode (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_set_forwarding (GstHarness * h, gboolean forwarding);
-
-/* buffers */
-
-GST_CHECK_API
-GstBuffer * gst_harness_create_buffer (GstHarness * h, gsize size);
-
-GST_CHECK_API
-GstFlowReturn gst_harness_push (GstHarness * h, GstBuffer * buffer);
-
-GST_CHECK_API
-GstBuffer * gst_harness_pull (GstHarness * h);
-
-GST_CHECK_API
-GstBuffer * gst_harness_try_pull (GstHarness * h);
-
-GST_CHECK_API
-gboolean gst_harness_pull_until_eos (GstHarness * h, GstBuffer ** buf);
-
-GST_CHECK_API
-GstBuffer * gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer);
-
-GST_CHECK_API
-guint gst_harness_buffers_received (GstHarness * h);
-
-GST_CHECK_API
-guint gst_harness_buffers_in_queue (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers);
-
-GST_CHECK_API
-void gst_harness_dump_to_file (GstHarness * h, const gchar * filename);
-
-GST_CHECK_API
-guint8 * gst_harness_take_all_data (GstHarness * h, gsize * size);
-
-GST_CHECK_API
-GstBuffer * gst_harness_take_all_data_as_buffer (GstHarness * h);
-
-GST_CHECK_API
-GBytes * gst_harness_take_all_data_as_bytes (GstHarness * h);
-
-GST_CHECK_API
-GstClockTime gst_harness_get_last_pushed_timestamp (GstHarness * h);
-
-/* downstream events */
-
-GST_CHECK_API
-gboolean gst_harness_push_event (GstHarness * h, GstEvent * event);
-
-GST_CHECK_API
-GstEvent * gst_harness_pull_event (GstHarness * h);
-
-GST_CHECK_API
-GstEvent * gst_harness_try_pull_event (GstHarness * h);
-
-GST_CHECK_API
-guint gst_harness_events_received (GstHarness * h);
-
-GST_CHECK_API
-guint gst_harness_events_in_queue (GstHarness * h);
-
-/* upstream events */
-
-GST_CHECK_API
-gboolean gst_harness_push_upstream_event (GstHarness * h, GstEvent * event);
-
-GST_CHECK_API
-GstEvent * gst_harness_pull_upstream_event (GstHarness * h);
-
-GST_CHECK_API
-GstEvent * gst_harness_try_pull_upstream_event (GstHarness * h);
-
-GST_CHECK_API
-guint gst_harness_upstream_events_received (GstHarness * h);
-
-GST_CHECK_API
-guint gst_harness_upstream_events_in_queue (GstHarness * h);
-
-/* latency */
-
-GST_CHECK_API
-GstClockTime gst_harness_query_latency (GstHarness * h);
-
-GST_CHECK_API
-void gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency);
-
-GST_CHECK_API
-void gst_harness_set_live (GstHarness * h, gboolean is_live);
-
-/* allocation query parameters */
-
-GST_CHECK_API
-void gst_harness_set_propose_allocator (GstHarness * h,
- GstAllocator * allocator,
- const GstAllocationParams * params);
-
-GST_CHECK_API
-void gst_harness_get_allocator (GstHarness * h,
- GstAllocator ** allocator,
- GstAllocationParams * params);
-
-GST_CHECK_API
-void gst_harness_add_propose_allocation_meta (GstHarness * h,
- GType api,
- const GstStructure * params);
-
-/* src-harness */
-
-GST_CHECK_API
-void gst_harness_add_src_harness (GstHarness * h,
- GstHarness * src_harness,
- gboolean has_clock_wait);
-
-GST_CHECK_API
-void gst_harness_add_src (GstHarness * h,
- const gchar * src_element_name,
- gboolean has_clock_wait);
-
-GST_CHECK_API
-void gst_harness_add_src_parse (GstHarness * h,
- const gchar * launchline,
- gboolean has_clock_wait);
-
-GST_CHECK_API
-GstFlowReturn gst_harness_push_from_src (GstHarness * h);
-
-GST_CHECK_API
-GstFlowReturn gst_harness_src_crank_and_push_many (GstHarness * h,
- gint cranks,
- gint pushes);
-
-GST_CHECK_API
-gboolean gst_harness_src_push_event (GstHarness * h);
-
-/* sink-harness */
-
-GST_CHECK_API
-void gst_harness_add_sink_harness (GstHarness * h,
- GstHarness * sink_harness);
-
-GST_CHECK_API
-void gst_harness_add_sink (GstHarness * h,
- const gchar * sink_element_name);
-
-GST_CHECK_API
-void gst_harness_add_sink_parse (GstHarness * h,
- const gchar * launchline);
-
-GST_CHECK_API
-GstFlowReturn gst_harness_push_to_sink (GstHarness * h);
-
-GST_CHECK_API
-GstFlowReturn gst_harness_sink_push_many (GstHarness * h, gint pushes);
-
-/* convenience functions */
-
-GST_CHECK_API
-GstElement * gst_harness_find_element (GstHarness * h,
- const gchar * element_name);
-
-GST_CHECK_API
-void gst_harness_set (GstHarness * h,
- const gchar * element_name,
- const gchar * first_property_name, ...) G_GNUC_NULL_TERMINATED;
-
-GST_CHECK_API
-void gst_harness_get (GstHarness * h,
- const gchar * element_name,
- const gchar * first_property_name, ...) G_GNUC_NULL_TERMINATED;
-
-GST_CHECK_API
-void gst_harness_add_probe (GstHarness * h,
- const gchar * element_name,
- const gchar * pad_name,
- GstPadProbeType mask,
- GstPadProbeCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_data);
-
-/* Stress */
-
-GST_CHECK_API
-guint gst_harness_stress_thread_stop (GstHarnessThread * t);
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_custom_start (GstHarness * h,
- GFunc init,
- GFunc callback,
- gpointer data,
- gulong sleep);
-
-#define gst_harness_stress_statechange_start(h) \
- gst_harness_stress_statechange_start_full (h, G_USEC_PER_SEC / 100)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_statechange_start_full (GstHarness * h,
- gulong sleep);
-
-#define gst_harness_stress_push_buffer_start(h, c, s, b) \
- gst_harness_stress_push_buffer_start_full (h, c, s, b, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_buffer_start_full (GstHarness * h,
- GstCaps * caps,
- const GstSegment * segment,
- GstBuffer * buf,
- gulong sleep);
-
-/**
- * GstHarnessPrepareBufferFunc:
- * @h: a #GstHarness
- * @data: user data
- *
- * Since: 1.6
- */
-typedef GstBuffer * (*GstHarnessPrepareBufferFunc) (GstHarness * h, gpointer data);
-
-#define gst_harness_stress_push_buffer_with_cb_start(h, c, s, f, d, n) \
- gst_harness_stress_push_buffer_with_cb_start_full (h, c, s, f, d, n, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h,
- GstCaps * caps,
- const GstSegment * segment,
- GstHarnessPrepareBufferFunc func,
- gpointer data,
- GDestroyNotify notify,
- gulong sleep);
-
-#define gst_harness_stress_push_event_start(h, e) \
- gst_harness_stress_push_event_start_full (h, e, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_event_start_full (GstHarness * h,
- GstEvent * event,
- gulong sleep);
-
-/**
- * GstHarnessPrepareEventFunc:
- * @h: a #GstHarness
- * @data: user data
- *
- * Since: 1.8
- */
-typedef GstEvent * (*GstHarnessPrepareEventFunc) (GstHarness * h, gpointer data);
-
-#define gst_harness_stress_push_event_with_cb_start(h, f, d, n) \
- gst_harness_stress_push_event_with_cb_start_full (h, f, d, n, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_event_with_cb_start_full (GstHarness * h,
- GstHarnessPrepareEventFunc func,
- gpointer data,
- GDestroyNotify notify,
- gulong sleep);
-
-#define gst_harness_stress_send_upstream_event_start(h, e) \
- gst_harness_stress_push_upstream_event_start_full (h, e, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_upstream_event_start_full (GstHarness * h,
- GstEvent * event,
- gulong sleep);
-
-#define gst_harness_stress_send_upstream_event_with_cb_start(h, f, d, n) \
- gst_harness_stress_push_upstream_event_with_cb_start_full (h, f, d, n, 0)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h,
- GstHarnessPrepareEventFunc func,
- gpointer data,
- GDestroyNotify notify,
- gulong sleep);
-
-
-#define gst_harness_stress_property_start(h, n, v) \
- gst_harness_stress_property_start_full (h, n, v, G_USEC_PER_SEC / 1000)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_property_start_full (GstHarness * h,
- const gchar * name,
- const GValue * value,
- gulong sleep);
-
-#define gst_harness_stress_requestpad_start(h, t, n, c, r) \
- gst_harness_stress_requestpad_start_full (h, t, n, c, r, G_USEC_PER_SEC / 100)
-
-GST_CHECK_API
-GstHarnessThread * gst_harness_stress_requestpad_start_full (GstHarness * h,
- GstPadTemplate * templ,
- const gchar * name,
- GstCaps * caps,
- gboolean release,
- gulong sleep);
-
-G_END_DECLS
-
-#endif /* __GST_HARNESS_H__ */
diff --git a/libs/gst/check/gsttestclock.c b/libs/gst/check/gsttestclock.c
deleted file mode 100644
index 83aadc426f..0000000000
--- a/libs/gst/check/gsttestclock.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/* GstTestClock - A deterministic clock for GStreamer unit tests
- *
- * Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
- * Copyright (C) 2012 Sebastian Rasmussen <sebastian.rasmussen@axis.com>
- * Copyright (C) 2012 Havard Graff <havard@pexip.com>
- * Copyright (C) 2013 Haakon Sporsheim <haakon@pexip.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:gsttestclock
- * @title: GstTestClock
- * @short_description: Controllable, deterministic clock for GStreamer unit tests
- * @see_also: #GstSystemClock, #GstClock
- *
- * GstTestClock is an implementation of #GstClock which has different
- * behaviour compared to #GstSystemClock. Time for #GstSystemClock advances
- * according to the system time, while time for #GstTestClock changes only
- * when gst_test_clock_set_time() or gst_test_clock_advance_time() are
- * called. #GstTestClock provides unit tests with the possibility to
- * precisely advance the time in a deterministic manner, independent of the
- * system time or any other external factors.
- *
- * ## Advancing the time of a #GstTestClock
- *
- * |[<!-- language="C" -->
- * #include <gst/gst.h>
- * #include <gst/check/gsttestclock.h>
- *
- * GstClock *clock;
- * GstTestClock *test_clock;
- *
- * clock = gst_test_clock_new ();
- * test_clock = GST_TEST_CLOCK (clock);
- * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
- * gst_test_clock_advance_time ( test_clock, 1 * GST_SECOND);
- * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
- * g_usleep (10 * G_USEC_PER_SEC);
- * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
- * gst_test_clock_set_time (test_clock, 42 * GST_SECOND);
- * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
- * ...
- * ]|
- *
- * #GstClock allows for setting up single shot or periodic clock notifications
- * as well as waiting for these notifications synchronously (using
- * gst_clock_id_wait()) or asynchronously (using gst_clock_id_wait_async() or
- * gst_clock_id_wait_async()). This is used by many GStreamer elements,
- * among them #GstBaseSrc and #GstBaseSink.
- *
- * #GstTestClock keeps track of these clock notifications. By calling
- * gst_test_clock_wait_for_next_pending_id() or
- * gst_test_clock_wait_for_multiple_pending_ids() a unit tests may wait for the
- * next one or several clock notifications to be requested. Additionally unit
- * tests may release blocked waits in a controlled fashion by calling
- * gst_test_clock_process_next_clock_id(). This way a unit test can control the
- * inaccuracy (jitter) of clock notifications, since the test can decide to
- * release blocked waits when the clock time has advanced exactly to, or past,
- * the requested clock notification time.
- *
- * There are also interfaces for determining if a notification belongs to a
- * #GstTestClock or not, as well as getting the number of requested clock
- * notifications so far.
- *
- * N.B.: When a unit test waits for a certain amount of clock notifications to
- * be requested in gst_test_clock_wait_for_next_pending_id() or
- * gst_test_clock_wait_for_multiple_pending_ids() then these functions may block
- * for a long time. If they block forever then the expected clock notifications
- * were never requested from #GstTestClock, and so the assumptions in the code
- * of the unit test are wrong. The unit test case runner in gstcheck is
- * expected to catch these cases either by the default test case timeout or the
- * one set for the unit test by calling tcase_set_timeout\(\).
- *
- * The sample code below assumes that the element under test will delay a
- * buffer pushed on the source pad by some latency until it arrives on the sink
- * pad. Moreover it is assumed that the element will at some point call
- * gst_clock_id_wait() to synchronously wait for a specific time. The first
- * buffer sent will arrive exactly on time only delayed by the latency. The
- * second buffer will arrive a little late (7ms) due to simulated jitter in the
- * clock notification.
- *
- * ## Demonstration of how to work with clock notifications and #GstTestClock
- *
- * |[<!-- language="C" -->
- * #include <gst/gst.h>
- * #include <gst/check/gstcheck.h>
- * #include <gst/check/gsttestclock.h>
- *
- * GstClockTime latency;
- * GstElement *element;
- * GstPad *srcpad;
- * GstClock *clock;
- * GstTestClock *test_clock;
- * GstBuffer buf;
- * GstClockID pending_id;
- * GstClockID processed_id;
- *
- * latency = 42 * GST_MSECOND;
- * element = create_element (latency, ...);
- * srcpad = get_source_pad (element);
- *
- * clock = gst_test_clock_new ();
- * test_clock = GST_TEST_CLOCK (clock);
- * gst_element_set_clock (element, clock);
- *
- * GST_INFO ("Set time, create and push the first buffer\n");
- * gst_test_clock_set_time (test_clock, 0);
- * buf = create_test_buffer (gst_clock_get_time (clock), ...);
- * gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
- *
- * GST_INFO ("Block until element is waiting for a clock notification\n");
- * gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
- * GST_INFO ("Advance to the requested time of the clock notification\n");
- * gst_test_clock_advance_time (test_clock, latency);
- * GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
- * processed_id = gst_test_clock_process_next_clock_id (test_clock);
- * g_assert (processed_id == pending_id);
- * g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
- * gst_clock_id_unref (pending_id);
- * gst_clock_id_unref (processed_id);
- *
- * GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
- * g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
- * buf = get_buffer_pushed_by_element (element, ...);
- * g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency);
- * gst_buffer_unref (buf);
- * GST_INFO ("Check that element does not wait for any clock notification\n");
- * g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
- *
- * GST_INFO ("Set time, create and push the second buffer\n");
- * gst_test_clock_advance_time (test_clock, 10 * GST_SECOND);
- * buf = create_test_buffer (gst_clock_get_time (clock), ...);
- * gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
- *
- * GST_INFO ("Block until element is waiting for a new clock notification\n");
- * (gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
- * GST_INFO ("Advance past 7ms beyond the requested time of the clock notification\n");
- * gst_test_clock_advance_time (test_clock, latency + 7 * GST_MSECOND);
- * GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
- * processed_id = gst_test_clock_process_next_clock_id (test_clock);
- * g_assert (processed_id == pending_id);
- * g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
- * gst_clock_id_unref (pending_id);
- * gst_clock_id_unref (processed_id);
- *
- * GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
- * g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
- * buf = get_buffer_pushed_by_element (element, ...);
- * g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==,
- * 10 * GST_SECOND + latency + 7 * GST_MSECOND);
- * gst_buffer_unref (buf);
- * GST_INFO ("Check that element does not wait for any clock notification\n");
- * g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
- * ...
- * ]|
- *
- * Since #GstTestClock is only supposed to be used in unit tests it calls
- * g_assert(), g_assert_cmpint() or g_assert_cmpuint() to validate all function
- * arguments. This will highlight any issues with the unit test code itself.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gsttestclock.h"
-
-enum
-{
- PROP_0,
- PROP_START_TIME,
- PROP_CLOCK_TYPE
-};
-
-typedef struct _GstClockEntryContext GstClockEntryContext;
-
-struct _GstClockEntryContext
-{
- GstClockEntry *clock_entry;
- GstClockTimeDiff time_diff;
-};
-
-struct _GstTestClockPrivate
-{
- GstClockType clock_type;
- GstClockTime start_time;
- GstClockTime internal_time;
- GList *entry_contexts;
- GCond entry_added_cond;
- GCond entry_processed_cond;
-};
-
-#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC
-
-#define GST_TEST_CLOCK_GET_PRIVATE(obj) ((GST_TEST_CLOCK_CAST (obj))->priv)
-
-GST_DEBUG_CATEGORY_STATIC (test_clock_debug);
-#define GST_CAT_TEST_CLOCK test_clock_debug
-
-#define _do_init \
-G_STMT_START { \
- GST_DEBUG_CATEGORY_INIT (test_clock_debug, "GST_TEST_CLOCK", \
- GST_DEBUG_BOLD, "Test clocks for unit tests"); \
-} G_STMT_END
-
-G_DEFINE_TYPE_WITH_CODE (GstTestClock, gst_test_clock,
- GST_TYPE_CLOCK, G_ADD_PRIVATE (GstTestClock) _do_init);
-
-static GstObjectClass *parent_class = NULL;
-
-static void gst_test_clock_constructed (GObject * object);
-static void gst_test_clock_dispose (GObject * object);
-static void gst_test_clock_finalize (GObject * object);
-static void gst_test_clock_get_property (GObject * object, guint property_id,
- GValue * value, GParamSpec * pspec);
-static void gst_test_clock_set_property (GObject * object, guint property_id,
- const GValue * value, GParamSpec * pspec);
-
-static GstClockTime gst_test_clock_get_resolution (GstClock * clock);
-static GstClockTime gst_test_clock_get_internal_time (GstClock * clock);
-static GstClockReturn gst_test_clock_wait (GstClock * clock,
- GstClockEntry * entry, GstClockTimeDiff * jitter);
-static GstClockReturn gst_test_clock_wait_async (GstClock * clock,
- GstClockEntry * entry);
-static void gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry);
-
-static gboolean gst_test_clock_peek_next_pending_id_unlocked (GstTestClock *
- test_clock, GstClockID * pending_id);
-static guint gst_test_clock_peek_id_count_unlocked (GstTestClock * test_clock);
-
-static void gst_test_clock_add_entry (GstTestClock * test_clock,
- GstClockEntry * entry, GstClockTimeDiff * jitter);
-static void gst_test_clock_remove_entry (GstTestClock * test_clock,
- GstClockEntry * entry);
-static GstClockEntryContext *gst_test_clock_lookup_entry_context (GstTestClock *
- test_clock, GstClockEntry * clock_entry);
-
-static gint gst_clock_entry_context_compare_func (gconstpointer a,
- gconstpointer b);
-
-static void
-gst_test_clock_class_init (GstTestClockClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstClockClass *gstclock_class = GST_CLOCK_CLASS (klass);
- GParamSpec *pspec;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->constructed = GST_DEBUG_FUNCPTR (gst_test_clock_constructed);
- gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_test_clock_dispose);
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_test_clock_finalize);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_test_clock_get_property);
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_test_clock_set_property);
-
- gstclock_class->get_resolution =
- GST_DEBUG_FUNCPTR (gst_test_clock_get_resolution);
- gstclock_class->get_internal_time =
- GST_DEBUG_FUNCPTR (gst_test_clock_get_internal_time);
- gstclock_class->wait = GST_DEBUG_FUNCPTR (gst_test_clock_wait);
- gstclock_class->wait_async = GST_DEBUG_FUNCPTR (gst_test_clock_wait_async);
- gstclock_class->unschedule = GST_DEBUG_FUNCPTR (gst_test_clock_unschedule);
-
- /**
- * GstTestClock:start-time:
- *
- * When a #GstTestClock is constructed it will have a certain start time set.
- * If the clock was created using gst_test_clock_new_with_start_time() then
- * this property contains the value of the @start_time argument. If
- * gst_test_clock_new() was called the clock started at time zero, and thus
- * this property contains the value 0.
- */
- pspec = g_param_spec_uint64 ("start-time", "Start Time",
- "Start Time of the Clock", 0, G_MAXUINT64, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property (gobject_class, PROP_START_TIME, pspec);
-
- g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
- g_param_spec_enum ("clock-type", "Clock type",
- "The kind of clock implementation to be reported by this clock",
- GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-}
-
-static void
-gst_test_clock_init (GstTestClock * test_clock)
-{
- GstTestClockPrivate *priv;
-
- test_clock->priv = gst_test_clock_get_instance_private (test_clock);
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- g_cond_init (&priv->entry_added_cond);
- g_cond_init (&priv->entry_processed_cond);
- priv->clock_type = DEFAULT_CLOCK_TYPE;
-
- GST_OBJECT_FLAG_SET (test_clock,
- GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
- GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
- GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
- GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
-}
-
-static void
-gst_test_clock_constructed (GObject * object)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (object);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- priv->internal_time = priv->start_time;
-
- G_OBJECT_CLASS (parent_class)->constructed (object);
-}
-
-static void
-gst_test_clock_dispose (GObject * object)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (object);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- while (priv->entry_contexts != NULL) {
- GstClockEntryContext *ctx = priv->entry_contexts->data;
- gst_test_clock_remove_entry (test_clock, ctx->clock_entry);
- }
-
- GST_OBJECT_UNLOCK (test_clock);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-gst_test_clock_finalize (GObject * object)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (object);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- g_cond_clear (&priv->entry_added_cond);
- g_cond_clear (&priv->entry_processed_cond);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_test_clock_get_property (GObject * object, guint property_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (object);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- switch (property_id) {
- case PROP_START_TIME:
- g_value_set_uint64 (value, priv->start_time);
- break;
- case PROP_CLOCK_TYPE:
- g_value_set_enum (value, priv->clock_type);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gst_test_clock_set_property (GObject * object, guint property_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (object);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- switch (property_id) {
- case PROP_START_TIME:
- priv->start_time = g_value_get_uint64 (value);
- GST_CAT_TRACE_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "test clock start time initialized at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (priv->start_time));
- break;
- case PROP_CLOCK_TYPE:
- priv->clock_type = (GstClockType) g_value_get_enum (value);
- GST_CAT_DEBUG (GST_CAT_TEST_CLOCK, "clock-type set to %d",
- priv->clock_type);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static GstClockTime
-gst_test_clock_get_resolution (GstClock * clock)
-{
- (void) clock;
- return 1;
-}
-
-static GstClockTime
-gst_test_clock_get_internal_time (GstClock * clock)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (clock);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GstClockTime result;
-
- GST_OBJECT_LOCK (test_clock);
-
- GST_CAT_TRACE_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "retrieving test clock time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (priv->internal_time));
- result = priv->internal_time;
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-static GstClockReturn
-gst_test_clock_wait (GstClock * clock,
- GstClockEntry * entry, GstClockTimeDiff * jitter)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (clock);
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "requesting synchronous clock notification at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));
-
- if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)
- goto was_unscheduled;
-
- if (gst_test_clock_lookup_entry_context (test_clock, entry) == NULL)
- gst_test_clock_add_entry (test_clock, entry, jitter);
-
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY;
-
- while (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_BUSY)
- g_cond_wait (&priv->entry_processed_cond, GST_OBJECT_GET_LOCK (test_clock));
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return GST_CLOCK_ENTRY_STATUS (entry);
-
- /* ERRORS */
-was_unscheduled:
- {
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "entry was unscheduled");
- GST_OBJECT_UNLOCK (test_clock);
- return GST_CLOCK_UNSCHEDULED;
- }
-}
-
-static GstClockReturn
-gst_test_clock_wait_async (GstClock * clock, GstClockEntry * entry)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)
- goto was_unscheduled;
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "requesting asynchronous clock notification at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));
-
- gst_test_clock_add_entry (test_clock, entry, NULL);
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return GST_CLOCK_OK;
-
- /* ERRORS */
-was_unscheduled:
- {
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "entry was unscheduled");
- GST_OBJECT_UNLOCK (test_clock);
- return GST_CLOCK_UNSCHEDULED;
- }
-}
-
-static void
-gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry)
-{
- GstTestClock *test_clock = GST_TEST_CLOCK (clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "unscheduling requested clock notification at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));
-
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_UNSCHEDULED;
- gst_test_clock_remove_entry (test_clock, entry);
-
- GST_OBJECT_UNLOCK (test_clock);
-}
-
-static gboolean
-gst_test_clock_peek_next_pending_id_unlocked (GstTestClock * test_clock,
- GstClockID * pending_id)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GList *imminent_clock_id = g_list_first (priv->entry_contexts);
- gboolean result = FALSE;
-
- if (imminent_clock_id != NULL) {
- GstClockEntryContext *ctx = imminent_clock_id->data;
-
- if (pending_id != NULL) {
- *pending_id = gst_clock_id_ref (ctx->clock_entry);
- }
-
- result = TRUE;
- }
-
- return result;
-}
-
-static guint
-gst_test_clock_peek_id_count_unlocked (GstTestClock * test_clock)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- return g_list_length (priv->entry_contexts);
-}
-
-static void
-gst_test_clock_add_entry (GstTestClock * test_clock,
- GstClockEntry * entry, GstClockTimeDiff * jitter)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GstClockTime now;
- GstClockEntryContext *ctx;
-
- now = gst_clock_adjust_unlocked (GST_CLOCK (test_clock), priv->internal_time);
-
- if (jitter != NULL)
- *jitter = GST_CLOCK_DIFF (GST_CLOCK_ENTRY_TIME (entry), now);
-
- ctx = g_slice_new (GstClockEntryContext);
- ctx->clock_entry = GST_CLOCK_ENTRY (gst_clock_id_ref (entry));
- ctx->time_diff = GST_CLOCK_DIFF (now, GST_CLOCK_ENTRY_TIME (entry));
-
- priv->entry_contexts = g_list_insert_sorted (priv->entry_contexts, ctx,
- gst_clock_entry_context_compare_func);
-
- g_cond_broadcast (&priv->entry_added_cond);
-}
-
-static void
-gst_test_clock_remove_entry (GstTestClock * test_clock, GstClockEntry * entry)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GstClockEntryContext *ctx;
-
- ctx = gst_test_clock_lookup_entry_context (test_clock, entry);
- if (ctx != NULL) {
- gst_clock_id_unref (ctx->clock_entry);
- priv->entry_contexts = g_list_remove (priv->entry_contexts, ctx);
- g_slice_free (GstClockEntryContext, ctx);
-
- g_cond_broadcast (&priv->entry_processed_cond);
- }
-}
-
-static GstClockEntryContext *
-gst_test_clock_lookup_entry_context (GstTestClock * test_clock,
- GstClockEntry * clock_entry)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GstClockEntryContext *result = NULL;
- GList *cur;
-
- for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) {
- GstClockEntryContext *ctx = cur->data;
-
- if (ctx->clock_entry == clock_entry) {
- result = ctx;
- break;
- }
- }
-
- return result;
-}
-
-static gint
-gst_clock_entry_context_compare_func (gconstpointer a, gconstpointer b)
-{
- const GstClockEntryContext *ctx_a = a;
- const GstClockEntryContext *ctx_b = b;
-
- return gst_clock_id_compare_func (ctx_a->clock_entry, ctx_b->clock_entry);
-}
-
-static void
-process_entry_context_unlocked (GstTestClock * test_clock,
- GstClockEntryContext * ctx)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GstClockEntry *entry = ctx->clock_entry;
-
- if (ctx->time_diff >= 0)
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK;
- else
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_EARLY;
-
- if (entry->func != NULL) {
- GST_OBJECT_UNLOCK (test_clock);
- entry->func (GST_CLOCK (test_clock), priv->internal_time, entry,
- entry->user_data);
- GST_OBJECT_LOCK (test_clock);
- }
-
- gst_test_clock_remove_entry (test_clock, entry);
-
- if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_PERIODIC) {
- GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry);
-
- if (entry->func != NULL)
- gst_test_clock_add_entry (test_clock, entry, NULL);
- }
-}
-
-static GList *
-gst_test_clock_get_pending_id_list_unlocked (GstTestClock * test_clock)
-{
- GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
- GQueue queue = G_QUEUE_INIT;
- GList *cur;
-
- for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) {
- GstClockEntryContext *ctx = cur->data;
-
- g_queue_push_tail (&queue, gst_clock_id_ref (ctx->clock_entry));
- }
-
- return queue.head;
-}
-
-/**
- * gst_test_clock_new:
- *
- * Creates a new test clock with its time set to zero.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstTestClock cast to #GstClock.
- *
- * Since: 1.2
- */
-GstClock *
-gst_test_clock_new (void)
-{
- return gst_test_clock_new_with_start_time (0);
-}
-
-/**
- * gst_test_clock_new_with_start_time:
- * @start_time: a #GstClockTime set to the desired start time of the clock.
- *
- * Creates a new test clock with its time set to the specified time.
- *
- * MT safe.
- *
- * Returns: (transfer full): a #GstTestClock cast to #GstClock.
- *
- * Since: 1.2
- */
-GstClock *
-gst_test_clock_new_with_start_time (GstClockTime start_time)
-{
- GstClock *clock;
-
- g_assert_cmpuint (start_time, !=, GST_CLOCK_TIME_NONE);
- clock = g_object_new (GST_TYPE_TEST_CLOCK, "start-time", start_time, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (clock);
-
- return clock;
-}
-
-/**
- * gst_test_clock_set_time:
- * @test_clock: a #GstTestClock of which to set the time
- * @new_time: a #GstClockTime later than that returned by gst_clock_get_time()
- *
- * Sets the time of @test_clock to the time given by @new_time. The time of
- * @test_clock is monotonically increasing, therefore providing a @new_time
- * which is earlier or equal to the time of the clock as given by
- * gst_clock_get_time() is a programming error.
- *
- * MT safe.
- *
- * Since: 1.2
- */
-void
-gst_test_clock_set_time (GstTestClock * test_clock, GstClockTime new_time)
-{
- GstTestClockPrivate *priv;
-
- g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- g_assert_cmpuint (new_time, !=, GST_CLOCK_TIME_NONE);
-
- GST_OBJECT_LOCK (test_clock);
-
- g_assert_cmpuint (new_time, >=, priv->internal_time);
-
- priv->internal_time = new_time;
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "clock set to %" GST_TIME_FORMAT, GST_TIME_ARGS (new_time));
-
- GST_OBJECT_UNLOCK (test_clock);
-}
-
-/**
- * gst_test_clock_advance_time:
- * @test_clock: a #GstTestClock for which to increase the time
- * @delta: a positive #GstClockTimeDiff to be added to the time of the clock
- *
- * Advances the time of the @test_clock by the amount given by @delta. The
- * time of @test_clock is monotonically increasing, therefore providing a
- * @delta which is negative or zero is a programming error.
- *
- * MT safe.
- *
- * Since: 1.2
- */
-void
-gst_test_clock_advance_time (GstTestClock * test_clock, GstClockTimeDiff delta)
-{
- GstTestClockPrivate *priv;
-
- g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- g_assert_cmpint (delta, >=, 0);
- g_assert_cmpuint (delta, <, G_MAXUINT64 - delta);
-
- GST_OBJECT_LOCK (test_clock);
-
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "advancing clock by %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (delta), GST_TIME_ARGS (priv->internal_time + delta));
- priv->internal_time += delta;
-
- GST_OBJECT_UNLOCK (test_clock);
-}
-
-/**
- * gst_test_clock_peek_id_count:
- * @test_clock: a #GstTestClock for which to count notifications
- *
- * Determine the number of pending clock notifications that have been
- * requested from the @test_clock.
- *
- * MT safe.
- *
- * Returns: the number of pending clock notifications.
- *
- * Since: 1.2
- */
-guint
-gst_test_clock_peek_id_count (GstTestClock * test_clock)
-{
- guint result;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0);
-
- GST_OBJECT_LOCK (test_clock);
- result = gst_test_clock_peek_id_count_unlocked (test_clock);
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_has_id:
- * @test_clock: a #GstTestClock to ask if it provided the notification
- * @id: (transfer none): a #GstClockID clock notification
- *
- * Checks whether @test_clock was requested to provide the clock notification
- * given by @id.
- *
- * MT safe.
- *
- * Returns: %TRUE if the clock has been asked to provide the given clock
- * notification, %FALSE otherwise.
- *
- * Since: 1.2
- */
-gboolean
-gst_test_clock_has_id (GstTestClock * test_clock, GstClockID id)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE);
- g_assert (id != NULL);
-
- GST_OBJECT_LOCK (test_clock);
- result = gst_test_clock_lookup_entry_context (test_clock, id) != NULL;
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_peek_next_pending_id:
- * @test_clock: a #GstTestClock to check the clock notifications for
- * @pending_id: (allow-none) (out) (transfer full): a #GstClockID clock
- * notification to look for
- *
- * Determines if the @pending_id is the next clock notification scheduled to
- * be triggered given the current time of the @test_clock.
- *
- * MT safe.
- *
- * Return: %TRUE if @pending_id is the next clock notification to be
- * triggered, %FALSE otherwise.
- *
- * Since: 1.2
- */
-gboolean
-gst_test_clock_peek_next_pending_id (GstTestClock * test_clock,
- GstClockID * pending_id)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE);
-
- GST_OBJECT_LOCK (test_clock);
- result = gst_test_clock_peek_next_pending_id_unlocked (test_clock,
- pending_id);
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_wait_for_next_pending_id:
- * @test_clock: #GstTestClock for which to get the pending clock notification
- * @pending_id: (allow-none) (out) (transfer full): #GstClockID
- * with information about the pending clock notification
- *
- * Waits until a clock notification is requested from @test_clock. There is no
- * timeout for this wait, see the main description of #GstTestClock. A reference
- * to the pending clock notification is stored in @pending_id.
- *
- * MT safe.
- *
- * Since: 1.2
- */
-void
-gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock,
- GstClockID * pending_id)
-{
- GstTestClockPrivate *priv;
-
- g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- while (priv->entry_contexts == NULL)
- g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock));
-
- if (!gst_test_clock_peek_next_pending_id_unlocked (test_clock, pending_id))
- g_assert_not_reached ();
-
- GST_OBJECT_UNLOCK (test_clock);
-}
-
-/**
- * gst_test_clock_wait_for_pending_id_count:
- * @test_clock: #GstTestClock for which to await having enough pending clock
- * @count: the number of pending clock notifications to wait for
- *
- * Blocks until at least @count clock notifications have been requested from
- * @test_clock. There is no timeout for this wait, see the main description of
- * #GstTestClock.
- *
- * Since: 1.2
- *
- * Deprecated: use gst_test_clock_wait_for_multiple_pending_ids() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-void
-gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
- guint count)
-{
- gst_test_clock_wait_for_multiple_pending_ids (test_clock, count, NULL);
-}
-#endif
-
-/**
- * gst_test_clock_process_next_clock_id:
- * @test_clock: a #GstTestClock for which to retrieve the next pending clock
- * notification
- *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): a #GstClockID containing the next pending clock
- * notification.
- *
- * Since: 1.2
- */
-GstClockID
-gst_test_clock_process_next_clock_id (GstTestClock * test_clock)
-{
- GstTestClockPrivate *priv;
- GstClockID result = NULL;
- GstClockEntryContext *ctx = NULL;
- GList *cur;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), NULL);
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- for (cur = priv->entry_contexts; cur != NULL && result == NULL;
- cur = cur->next) {
- ctx = cur->data;
-
- if (priv->internal_time >= GST_CLOCK_ENTRY_TIME (ctx->clock_entry))
- result = gst_clock_id_ref (ctx->clock_entry);
- }
-
- if (result != NULL)
- process_entry_context_unlocked (test_clock, ctx);
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_get_next_entry_time:
- * @test_clock: a #GstTestClock to fetch the next clock notification time for
- *
- * Retrieve the requested time for the next pending clock notification.
- *
- * MT safe.
- *
- * Returns: a #GstClockTime set to the time of the next pending clock
- * notification. If no clock notifications have been requested
- * %GST_CLOCK_TIME_NONE will be returned.
- *
- * Since: 1.2
- */
-GstClockTime
-gst_test_clock_get_next_entry_time (GstTestClock * test_clock)
-{
- GstTestClockPrivate *priv;
- GstClockTime result = GST_CLOCK_TIME_NONE;
- GList *imminent_clock_id;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), GST_CLOCK_TIME_NONE);
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- /* The list of pending clock notifications is sorted by time,
- so the most imminent one is the first one in the list. */
- imminent_clock_id = g_list_first (priv->entry_contexts);
- if (imminent_clock_id != NULL) {
- GstClockEntryContext *ctx = imminent_clock_id->data;
- result = GST_CLOCK_ENTRY_TIME (ctx->clock_entry);
- }
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_wait_for_multiple_pending_ids:
- * @test_clock: #GstTestClock for which to await having enough pending clock
- * @count: the number of pending clock notifications to wait for
- * @pending_list: (out) (element-type Gst.ClockID) (transfer full) (allow-none): Address
- * of a #GList pointer variable to store the list of pending #GstClockIDs
- * that expired, or %NULL
- *
- * Blocks until at least @count clock notifications have been requested from
- * @test_clock. There is no timeout for this wait, see the main description of
- * #GstTestClock.
- *
- * MT safe.
- *
- * Since: 1.4
- */
-void
-gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
- guint count, GList ** pending_list)
-{
- GstTestClockPrivate *priv;
-
- g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- while (g_list_length (priv->entry_contexts) < count)
- g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock));
-
- if (pending_list)
- *pending_list = gst_test_clock_get_pending_id_list_unlocked (test_clock);
-
- GST_OBJECT_UNLOCK (test_clock);
-}
-
-/**
- * gst_test_clock_timed_wait_for_multiple_pending_ids:
- * @test_clock: #GstTestClock for which to await having enough pending clock
- * @count: the number of pending clock notifications to wait for
- * @timeout_ms: the timeout in milliseconds
- * @pending_list: (out) (element-type Gst.ClockID) (transfer full) (allow-none): Address
- * of a #GList pointer variable to store the list of pending #GstClockIDs
- * that expired, or %NULL
- *
- * Blocks until at least @count clock notifications have been requested from
- * @test_clock, or the timeout expires.
- *
- * MT safe.
- *
- * Returns: a @gboolean %TRUE if the waits have been registered, %FALSE if not.
- * (Could be that it timed out waiting or that more waits than waits was found)
- *
- * Since: 1.16
- */
-gboolean
-gst_test_clock_timed_wait_for_multiple_pending_ids (GstTestClock * test_clock,
- guint count, guint timeout_ms, GList ** pending_list)
-{
- GstTestClockPrivate *priv;
- gint64 timeout = g_get_monotonic_time () +
- timeout_ms * (G_USEC_PER_SEC / 1000);
- gboolean ret;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE);
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- while (g_list_length (priv->entry_contexts) < count &&
- g_get_monotonic_time () < timeout) {
- g_cond_wait_until (&priv->entry_added_cond,
- GST_OBJECT_GET_LOCK (test_clock), timeout);
- }
-
- if (pending_list)
- *pending_list = gst_test_clock_get_pending_id_list_unlocked (test_clock);
-
- ret = (g_list_length (priv->entry_contexts) == count);
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return ret;
-}
-
-
-/**
- * gst_test_clock_process_id:
- * @test_clock: #GstTestClock for which to process the pending IDs
- * @pending_id: (transfer full): #GstClockID
- *
- * Processes and releases the pending ID.
- *
- * MT safe.
- *
- * Since: 1.18
- */
-gboolean
-gst_test_clock_process_id (GstTestClock * test_clock, GstClockID pending_id)
-{
- GstClockEntryContext *ctx;
-
- gboolean result = FALSE;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE);
-
- GST_OBJECT_LOCK (test_clock);
-
- ctx = gst_test_clock_lookup_entry_context (test_clock, pending_id);
- g_assert (ctx);
-
- if (ctx) {
- process_entry_context_unlocked (test_clock, ctx);
- result = TRUE;
- gst_clock_id_unref (pending_id);
- }
-
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_process_id_list:
- * @test_clock: #GstTestClock for which to process the pending IDs
- * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List
- * of pending #GstClockIDs
- *
- * Processes and releases the pending IDs in the list.
- *
- * MT safe.
- *
- * Since: 1.4
- */
-guint
-gst_test_clock_process_id_list (GstTestClock * test_clock,
- const GList * pending_list)
-{
- const GList *cur;
- guint result = 0;
-
- g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0);
-
- GST_OBJECT_LOCK (test_clock);
-
- for (cur = pending_list; cur != NULL; cur = cur->next) {
- GstClockID pending_id = cur->data;
- GstClockEntryContext *ctx =
- gst_test_clock_lookup_entry_context (test_clock, pending_id);
- if (ctx) {
- process_entry_context_unlocked (test_clock, ctx);
- result++;
- }
- }
- GST_OBJECT_UNLOCK (test_clock);
-
- return result;
-}
-
-/**
- * gst_test_clock_id_list_get_latest_time:
- * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List
- * of of pending #GstClockIDs
- *
- * Finds the latest time inside the list.
- *
- * MT safe.
- *
- * Since: 1.4
- */
-GstClockTime
-gst_test_clock_id_list_get_latest_time (const GList * pending_list)
-{
- const GList *cur;
- GstClockTime result = 0;
-
- for (cur = pending_list; cur != NULL; cur = cur->next) {
- GstClockID *pending_id = cur->data;
- GstClockTime time = gst_clock_id_get_time (pending_id);
- if (time > result)
- result = time;
- }
-
- return result;
-}
-
-/**
- * gst_test_clock_crank:
- * @test_clock: #GstTestClock to crank
- *
- * A "crank" consists of three steps:
- * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
- * 2: Advance the #GstTestClock to the time the #GstClockID is waiting, unless
- * the clock time is already passed the clock id (Since: 1.18).
- * 3: Release the #GstClockID wait.
- * A "crank" can be though of as the notion of
- * manually driving the clock forward to its next logical step.
- *
- * Return: %TRUE if the crank was successful, %FALSE otherwise.
- *
- * MT safe.
- *
- * Since: 1.8
- */
-gboolean
-gst_test_clock_crank (GstTestClock * test_clock)
-{
- GstClockID res, pending;
- GstClockTime now;
- gboolean result;
-
- gst_test_clock_wait_for_next_pending_id (test_clock, &pending);
- now = gst_clock_get_time (GST_CLOCK (test_clock));
- if (gst_clock_id_get_time (pending) > now)
- gst_test_clock_set_time (test_clock, gst_clock_id_get_time (pending));
- res = gst_test_clock_process_next_clock_id (test_clock);
- if (G_LIKELY (res == pending)) {
- GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "cranked to time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (gst_clock_get_time (GST_CLOCK (test_clock))));
- result = TRUE;
- } else {
- GST_CAT_WARNING_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
- "testclock next id != pending (%p != %p)", res, pending);
- result = FALSE;
- }
-
- if (G_LIKELY (res != NULL))
- gst_clock_id_unref (res);
-
- gst_clock_id_unref (pending);
-
- return result;
-}
diff --git a/libs/gst/check/gsttestclock.h b/libs/gst/check/gsttestclock.h
deleted file mode 100644
index a1c1f5a88b..0000000000
--- a/libs/gst/check/gsttestclock.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* GstTestClock - A deterministic clock for GStreamer unit tests
- *
- * Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
- * Copyright (C) 2012 Sebastian Rasmussen <sebastian.rasmussen@axis.com>
- * Copyright (C) 2012 Havard Graff <havard@pexip.com>
- * Copyright (C) 2013 Haakon Sporsheim <haakon@pexip.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_TEST_CLOCK_H__
-#define __GST_TEST_CLOCK_H__
-
-#include <gst/gst.h>
-#include <gst/check/check-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TEST_CLOCK (gst_test_clock_get_type ())
-#define GST_TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
- GST_TYPE_TEST_CLOCK, GstTestClock))
-#define GST_IS_TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
- GST_TYPE_TEST_CLOCK))
-#define GST_TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
- GST_TYPE_TEST_CLOCK, GstTestClockClass))
-#define GST_IS_TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE (\
- (klass), GST_TYPE_TEST_CLOCK))
-#define GST_TEST_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS (\
- (obj), GST_TYPE_TEST_CLOCK, GstTestClockClass))
-#define GST_TEST_CLOCK_CAST(obj) ((GstTestClock*)(obj))
-
-typedef struct _GstTestClock GstTestClock;
-typedef struct _GstTestClockClass GstTestClockClass;
-typedef struct _GstTestClockPrivate GstTestClockPrivate;
-
-/**
- * GstTestClock:
- *
- * A #GstTestClock structure which is based on a #GstClock along with some
- * private data.
- *
- * Since: 1.2
- */
-struct _GstTestClock
-{
- GstClock parent;
-
- /*< private >*/
- GstTestClockPrivate *priv;
-};
-
-/**
- * GstTestClockClass:
- * @parent_class: the parent class structure
- *
- * The class of a #GstTestClock, which has no virtual methods to override.
- *
- * Since: 1.2
- */
-struct _GstTestClockClass
-{
- GstClockClass parent_class;
-};
-
-GST_CHECK_API
-GType gst_test_clock_get_type (void);
-
-GST_CHECK_API
-GstClock * gst_test_clock_new (void);
-
-GST_CHECK_API
-GstClock * gst_test_clock_new_with_start_time (GstClockTime start_time);
-
-GST_CHECK_API
-void gst_test_clock_set_time (GstTestClock * test_clock,
- GstClockTime new_time);
-
-GST_CHECK_API
-void gst_test_clock_advance_time (GstTestClock * test_clock,
- GstClockTimeDiff delta);
-
-GST_CHECK_API
-guint gst_test_clock_peek_id_count (GstTestClock * test_clock);
-
-GST_CHECK_API
-gboolean gst_test_clock_has_id (GstTestClock * test_clock, GstClockID id);
-
-GST_CHECK_API
-gboolean gst_test_clock_peek_next_pending_id (GstTestClock * test_clock,
- GstClockID * pending_id);
-
-GST_CHECK_API
-void gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock,
- GstClockID * pending_id);
-
-GST_CHECK_DEPRECATED_FOR(gst_test_clock_wait_for_multiple_pending_ids)
-void gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
- guint count);
-
-GST_CHECK_API
-GstClockID gst_test_clock_process_next_clock_id (GstTestClock * test_clock);
-
-GST_CHECK_API
-GstClockTime gst_test_clock_get_next_entry_time (GstTestClock * test_clock);
-
-GST_CHECK_API
-void gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
- guint count,
- GList ** pending_list);
-
-GST_CHECK_API
-gboolean gst_test_clock_timed_wait_for_multiple_pending_ids (GstTestClock * test_clock,
- guint count,
- guint timeout_ms,
- GList ** pending_list);
-
-GST_CHECK_API
-gboolean gst_test_clock_process_id (GstTestClock * test_clock,
- GstClockID pending_id);
-
-GST_CHECK_API
-guint gst_test_clock_process_id_list (GstTestClock * test_clock,
- const GList * pending_list);
-
-GST_CHECK_API
-GstClockTime gst_test_clock_id_list_get_latest_time (const GList * pending_list);
-
-GST_CHECK_API
-gboolean gst_test_clock_crank (GstTestClock * test_clock);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTestClock, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_TEST_CLOCK_H__ */
diff --git a/libs/gst/check/libcheck/README.txt b/libs/gst/check/libcheck/README.txt
deleted file mode 100644
index cc0f2ed27c..0000000000
--- a/libs/gst/check/libcheck/README.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a copy of libcheck, a unit testing framework for C:
-
-https://github.com/libcheck/check/
-
-The last update was on 9th December, with the following commit: ba42e7de3d62ea9d3699bf0709554b3e47a8f09e
-
-The check*.c files in this directory are the same as those in the src/
-directory in upstream. The files in the libcompat/ directory are the same as
-those in the lib/ directory upstream.
-
-lib/snprintf.c was omitted since we don't run on any platforms that don't
-provide snprintf and the upstream implementation is ~2000 lines.
-
-lib/malloc.c and lib/realloc.c were omitted since we were doing fine without
-them and it does a #define malloc rpl_malloc on Android because the malloc
-shipped with Bionic is not GNU-compliant. rpl_malloc is provided by libcheck,
-but not everything in gstreamer links against libcheck. We also don't care
-about this.
-
-Steps to sync with upstream:
-
-1. Clone libcheck from the above git repository
-2. Copy files into this directory
-3. Run GNU indent on all the code
-4. Fix internal #includes
-5. Manually inspect the diff
-6. Update configure.ac, m4/check-checks.m4, meson.build files, etc
-6. Run make check, then commit and push
-
-Any changes made to files in this directory must be submitted upstream via
-a pull request: https://github.com/libcheck/check/compare
-
-This involves creating an account on GitHub, forking libcheck/check there,
-pushing the changes into a branch, and then submitting it as a pull request.
diff --git a/libs/gst/check/libcheck/check.c b/libs/gst/check/libcheck/check.c
deleted file mode 100644
index 8ef3b62fc3..0000000000
--- a/libs/gst/check/libcheck/check.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <math.h>
-
-#include <glib.h>
-
-#include "internal-check.h"
-#include "check_error.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_msg.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> /* for _POSIX_VERSION */
-#endif
-
-#ifndef DEFAULT_TIMEOUT
-#define DEFAULT_TIMEOUT 4
-#endif
-
-/*
- * When a process exits either normally, with exit(), or
- * by an uncaught signal, The lower 0x377 bits are passed
- * to the parent. Of those, only the lower 8 bits are
- * returned by the WEXITSTATUS() macro.
- */
-#define WEXITSTATUS_MASK 0xFF
-
-int check_major_version = CHECK_MAJOR_VERSION;
-int check_minor_version = CHECK_MINOR_VERSION;
-int check_micro_version = CHECK_MICRO_VERSION;
-
-const char *current_test_name = NULL;
-
-static int non_pass (int val);
-static Fixture *fixture_create (SFun fun, int ischecked);
-static void tcase_add_fixture (TCase * tc, SFun setup, SFun teardown,
- int ischecked);
-static void tr_init (TestResult * tr);
-static void suite_free (Suite * s);
-static void tcase_free (TCase * tc);
-
-Suite *
-suite_create (const char *name)
-{
- Suite *s;
-
- s = (Suite *) emalloc (sizeof (Suite)); /* freed in suite_free */
- if (name == NULL)
- s->name = "";
- else
- s->name = name;
- s->tclst = check_list_create ();
- return s;
-}
-
-int
-suite_tcase (Suite * s, const char *tcname)
-{
- List *l;
- TCase *tc;
-
- if (s == NULL)
- return 0;
-
- l = s->tclst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- tc = (TCase *) check_list_val (l);
- if (strcmp (tcname, tc->name) == 0)
- return 1;
- }
-
- return 0;
-}
-
-static void
-suite_free (Suite * s)
-{
- List *l;
-
- if (s == NULL)
- return;
- l = s->tclst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- tcase_free ((TCase *) check_list_val (l));
- }
- check_list_free (s->tclst);
- free (s);
-}
-
-
-TCase *
-tcase_create (const char *name)
-{
- char *env;
- double timeout_sec = DEFAULT_TIMEOUT;
-
- TCase *tc = (TCase *) emalloc (sizeof (TCase)); /*freed in tcase_free */
-
- if (name == NULL)
- tc->name = "";
- else
- tc->name = name;
-
- env = getenv ("CK_DEFAULT_TIMEOUT");
- if (env != NULL) {
- char *endptr = NULL;
- double tmp = strtod (env, &endptr);
-
- if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
- timeout_sec = tmp;
- }
- }
-
- env = getenv ("CK_TIMEOUT_MULTIPLIER");
- if (env != NULL) {
- char *endptr = NULL;
- double tmp = strtod (env, &endptr);
-
- if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
- timeout_sec = timeout_sec * tmp;
- }
- }
-
- tc->timeout.tv_sec = (time_t) floor (timeout_sec);
- tc->timeout.tv_nsec =
- (long) ((timeout_sec - floor (timeout_sec)) * (double) NANOS_PER_SECONDS);
-
- tc->tflst = check_list_create ();
- tc->unch_sflst = check_list_create ();
- tc->ch_sflst = check_list_create ();
- tc->unch_tflst = check_list_create ();
- tc->ch_tflst = check_list_create ();
- tc->tags = check_list_create ();
-
- return tc;
-}
-
-/*
- * Helper function to create a list of tags from
- * a space separated string.
- */
-List *
-tag_string_to_list (const char *tags_string)
-{
- List *list;
- char *tags;
- char *tag;
-
- list = check_list_create ();
-
- if (NULL == tags_string) {
- return list;
- }
-
- tags = strdup (tags_string);
- tag = strtok (tags, " ");
- while (tag) {
- check_list_add_end (list, strdup (tag));
- tag = strtok (NULL, " ");
- }
- free (tags);
- return list;
-}
-
-void
-tcase_set_tags (TCase * tc, const char *tags_orig)
-{
- /* replace any pre-existing list */
- if (tc->tags) {
- check_list_apply (tc->tags, free);
- check_list_free (tc->tags);
- }
- tc->tags = tag_string_to_list (tags_orig);
-}
-
-static void
-tcase_free (TCase * tc)
-{
- check_list_apply (tc->tflst, free);
- check_list_apply (tc->unch_sflst, free);
- check_list_apply (tc->ch_sflst, free);
- check_list_apply (tc->unch_tflst, free);
- check_list_apply (tc->ch_tflst, free);
- check_list_apply (tc->tags, free);
- check_list_free (tc->tflst);
- check_list_free (tc->unch_sflst);
- check_list_free (tc->ch_sflst);
- check_list_free (tc->unch_tflst);
- check_list_free (tc->ch_tflst);
- check_list_free (tc->tags);
- free (tc);
-}
-
-unsigned int
-tcase_matching_tag (TCase * tc, List * check_for)
-{
-
- if (NULL == check_for) {
- return 0;
- }
-
- for (check_list_front (check_for); !check_list_at_end (check_for);
- check_list_advance (check_for)) {
- for (check_list_front (tc->tags); !check_list_at_end (tc->tags);
- check_list_advance (tc->tags)) {
- if (0 == strcmp ((const char *) check_list_val (tc->tags),
- (const char *) check_list_val (check_for))) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-void
-suite_add_tcase (Suite * s, TCase * tc)
-{
- if (s == NULL || tc == NULL || check_list_contains (s->tclst, tc)) {
- return;
- }
-
- check_list_add_end (s->tclst, tc);
-}
-
-void
-_tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal,
- int allowed_exit_value, int start, int end)
-{
- TF *tf;
-
- if (tc == NULL || fn == NULL || name == NULL)
- return;
- tf = (TF *) emalloc (sizeof (TF)); /* freed in tcase_free */
- tf->fn = fn;
- tf->loop_start = start;
- tf->loop_end = end;
- tf->signal = _signal; /* 0 means no signal expected */
- tf->allowed_exit_value = (WEXITSTATUS_MASK & allowed_exit_value); /* 0 is default successful exit */
- tf->name = name;
- check_list_add_end (tc->tflst, tf);
-}
-
-static Fixture *
-fixture_create (SFun fun, int ischecked)
-{
- Fixture *f;
-
- f = (Fixture *) emalloc (sizeof (Fixture));
- f->fun = fun;
- f->ischecked = ischecked;
-
- return f;
-}
-
-void
-tcase_add_unchecked_fixture (TCase * tc, SFun setup, SFun teardown)
-{
- tcase_add_fixture (tc, setup, teardown, 0);
-}
-
-void
-tcase_add_checked_fixture (TCase * tc, SFun setup, SFun teardown)
-{
- tcase_add_fixture (tc, setup, teardown, 1);
-}
-
-static void
-tcase_add_fixture (TCase * tc, SFun setup, SFun teardown, int ischecked)
-{
- if (setup) {
- if (ischecked)
- check_list_add_end (tc->ch_sflst, fixture_create (setup, ischecked));
- else
- check_list_add_end (tc->unch_sflst, fixture_create (setup, ischecked));
- }
-
- /* Add teardowns at front so they are run in reverse order. */
- if (teardown) {
- if (ischecked)
- check_list_add_front (tc->ch_tflst, fixture_create (teardown, ischecked));
- else
- check_list_add_front (tc->unch_tflst,
- fixture_create (teardown, ischecked));
- }
-}
-
-void
-tcase_set_timeout (TCase * tc, double timeout)
-{
-#if defined(HAVE_FORK)
- if (timeout >= 0) {
- char *env = getenv ("CK_TIMEOUT_MULTIPLIER");
-
- if (env != NULL) {
- char *endptr = NULL;
- double tmp = strtod (env, &endptr);
-
- if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
- timeout = timeout * tmp;
- }
- }
-
- tc->timeout.tv_sec = (time_t) floor (timeout);
- tc->timeout.tv_nsec =
- (long) ((timeout - floor (timeout)) * (double) NANOS_PER_SECONDS);
- }
-#else
- (void) tc;
- (void) timeout;
- eprintf
- ("This version does not support timeouts, as fork is not supported",
- __FILE__, __LINE__);
- /* Ignoring, as Check is not compiled with fork support. */
-#endif /* HAVE_FORK */
-}
-
-void
-tcase_fn_start (const char *fname, const char *file, int line)
-{
- send_ctx_info (CK_CTX_TEST);
- send_loc_info (file, line);
-
- current_test_name = fname;
-}
-
-const char *
-tcase_name ()
-{
- return current_test_name;
-}
-
-void
-_mark_point (const char *file, int line)
-{
- send_loc_info (file, line);
-}
-
-void
-_ck_assert_failed (const char *file, int line, const char *expr, ...)
-{
- const char *msg;
- va_list ap;
- char buf[BUFSIZ];
- const char *to_send;
-
- send_loc_info (file, line);
-
- va_start (ap, expr);
- msg = (const char *) va_arg (ap, char *);
-
- /*
- * If a message was passed, format it with vsnprintf.
- * Otherwise, print the expression as is.
- */
- if (msg != NULL) {
- vsnprintf (buf, BUFSIZ, msg, ap);
- to_send = buf;
- } else {
- to_send = expr;
- }
-
- va_end (ap);
- send_failure_info (to_send);
-#if defined(HAVE_FORK) && HAVE_FORK==1
- if (cur_fork_status () == CK_FORK) {
- g_thread_pool_stop_unused_threads ();
- _exit (1);
- }
-#endif /* HAVE_FORK */
- longjmp (error_jmp_buffer, 1);
-}
-
-SRunner *
-srunner_create (Suite * s)
-{
- SRunner *sr = (SRunner *) emalloc (sizeof (SRunner)); /* freed in srunner_free */
-
- sr->slst = check_list_create ();
- if (s != NULL)
- check_list_add_end (sr->slst, s);
- sr->stats = (TestStats *) emalloc (sizeof (TestStats)); /* freed in srunner_free */
- sr->stats->n_checked = sr->stats->n_failed = sr->stats->n_errors = 0;
- sr->resultlst = check_list_create ();
- sr->log_fname = NULL;
- sr->xml_fname = NULL;
- sr->tap_fname = NULL;
- sr->loglst = NULL;
-
-#if defined(HAVE_FORK)
- sr->fstat = CK_FORK_GETENV;
-#else
- /*
- * Overriding the default of running tests in fork mode,
- * as this system does not have fork()
- */
- sr->fstat = CK_NOFORK;
-#endif /* HAVE_FORK */
-
- return sr;
-}
-
-void
-srunner_add_suite (SRunner * sr, Suite * s)
-{
- if (s == NULL)
- return;
-
- check_list_add_end (sr->slst, s);
-}
-
-void
-srunner_free (SRunner * sr)
-{
- List *l;
- TestResult *tr;
-
- if (sr == NULL)
- return;
-
- free (sr->stats);
- l = sr->slst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- suite_free ((Suite *) check_list_val (l));
- }
- check_list_free (sr->slst);
-
- l = sr->resultlst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- tr = (TestResult *) check_list_val (l);
- tr_free (tr);
- }
- check_list_free (sr->resultlst);
-
- free (sr);
-}
-
-int
-srunner_ntests_failed (SRunner * sr)
-{
- return sr->stats->n_failed + sr->stats->n_errors;
-}
-
-int
-srunner_ntests_run (SRunner * sr)
-{
- return sr->stats->n_checked;
-}
-
-TestResult **
-srunner_failures (SRunner * sr)
-{
- int i = 0;
- TestResult **trarray;
- List *rlst;
-
- trarray =
- (TestResult **) emalloc (sizeof (trarray[0]) *
- srunner_ntests_failed (sr));
-
- rlst = sr->resultlst;
- for (check_list_front (rlst); !check_list_at_end (rlst);
- check_list_advance (rlst)) {
- TestResult *tr = (TestResult *) check_list_val (rlst);
-
- if (non_pass (tr->rtype))
- trarray[i++] = tr;
-
- }
- return trarray;
-}
-
-TestResult **
-srunner_results (SRunner * sr)
-{
- int i = 0;
- TestResult **trarray;
- List *rlst;
-
- trarray =
- (TestResult **) emalloc (sizeof (trarray[0]) * srunner_ntests_run (sr));
-
- rlst = sr->resultlst;
- for (check_list_front (rlst); !check_list_at_end (rlst);
- check_list_advance (rlst)) {
- trarray[i++] = (TestResult *) check_list_val (rlst);
- }
- return trarray;
-}
-
-static int
-non_pass (int val)
-{
- return val != CK_PASS;
-}
-
-TestResult *
-tr_create (void)
-{
- TestResult *tr;
-
- tr = (TestResult *) emalloc (sizeof (TestResult));
- tr_init (tr);
- return tr;
-}
-
-static void
-tr_init (TestResult * tr)
-{
- tr->ctx = CK_CTX_INVALID;
- tr->line = -1;
- tr->rtype = CK_TEST_RESULT_INVALID;
- tr->msg = NULL;
- tr->file = NULL;
- tr->tcname = NULL;
- tr->tname = NULL;
- tr->duration = -1;
-}
-
-void
-tr_free (TestResult * tr)
-{
- free (tr->file);
- free (tr->msg);
- free (tr);
-}
-
-
-const char *
-tr_msg (TestResult * tr)
-{
- return tr->msg;
-}
-
-int
-tr_lno (TestResult * tr)
-{
- return tr->line;
-}
-
-const char *
-tr_lfile (TestResult * tr)
-{
- return tr->file;
-}
-
-int
-tr_rtype (TestResult * tr)
-{
- return tr->rtype;
-}
-
-enum ck_result_ctx
-tr_ctx (TestResult * tr)
-{
- return tr->ctx;
-}
-
-const char *
-tr_tcname (TestResult * tr)
-{
- return tr->tcname;
-}
-
-static enum fork_status _fstat = CK_FORK;
-
-void
-set_fork_status (enum fork_status fstat)
-{
- if (fstat == CK_FORK || fstat == CK_NOFORK || fstat == CK_FORK_GETENV)
- _fstat = fstat;
- else
- eprintf ("Bad status in set_fork_status", __FILE__, __LINE__);
-}
-
-enum fork_status
-cur_fork_status (void)
-{
- return _fstat;
-}
-
-/**
- * Not all systems support the same clockid_t's. This call checks
- * if the CLOCK_MONOTONIC clockid_t is valid. If so, that is returned,
- * otherwise, CLOCK_REALTIME is returned.
- *
- * The clockid_t that was found to work on the first call is
- * cached for subsequent calls.
- */
-clockid_t
-check_get_clockid ()
-{
- static clockid_t clockid = -1;
-
- if (clockid == -1) {
-/*
- * Only check if we have librt available. Otherwise, the clockid
- * will be ignored anyway, as the clock_gettime() and
- * timer_create() functions will be re-implemented in libcompat.
- * Worse, if librt and alarm() are unavailable, this check
- * will result in an assert(0).
- */
-#if defined(HAVE_POSIX_TIMERS) && defined(HAVE_MONOTONIC_CLOCK)
- timer_t timerid;
-
- if (timer_create (CLOCK_MONOTONIC, NULL, &timerid) == 0) {
- timer_delete (timerid);
- clockid = CLOCK_MONOTONIC;
- } else {
- clockid = CLOCK_REALTIME;
- }
-#else
- clockid = CLOCK_MONOTONIC;
-#endif
- }
-
- return clockid;
-}
diff --git a/libs/gst/check/libcheck/check.h.in b/libs/gst/check/libcheck/check.h.in
deleted file mode 100644
index d52abc5c1a..0000000000
--- a/libs/gst/check/libcheck/check.h.in
+++ /dev/null
@@ -1,1328 +0,0 @@
-/*-*- mode:C; -*- */
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_H
-#define CHECK_H
-
-#include <stddef.h>
-#include <string.h>
-
-/*
- Macros and functions starting with _ (underscore) are internal and
- may change without notice. You have been warned!.
-*/
-
-
-#ifdef __cplusplus
-#define CK_CPPSTART extern "C" {
-#define CK_CPPEND }
-CK_CPPSTART
-#endif
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-#define GCC_VERSION_AT_LEAST(major, minor) \
-((__GNUC__ > (major)) || \
- (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
-#else
-#define GCC_VERSION_AT_LEAST(major, minor) 0
-#endif
-#if GCC_VERSION_AT_LEAST(2,95)
-#define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
-#else
-#define CK_ATTRIBUTE_UNUSED
-#endif /* GCC 2.95 */
-#if GCC_VERSION_AT_LEAST(2,5)
-#define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
-#else
-#define CK_ATTRIBUTE_NORETURN
-#endif /* GCC 2.5 */
-#include <sys/types.h>
-
-/*
- * Used to create the linker script for hiding lib-local symbols. Shall
- * be put directly in front of the exported symbol.
- */
-#define CK_EXPORT
-
-/*
- * Used for MSVC to create the export attribute
- * CK_DLL_EXP is defined during the compilation of the library
- * on the command line.
- */
-#ifndef CK_DLL_EXP
-# if defined(_MSC_VER)
-# define CK_DLL_EXP __declspec(dllimport)
-# else
-# define CK_DLL_EXP extern
-# endif
-#endif
-
-/* check version numbers */
-#define CHECK_MAJOR_VERSION (@CHECK_MAJOR_VERSION@)
-#define CHECK_MINOR_VERSION (@CHECK_MINOR_VERSION@)
-#define CHECK_MICRO_VERSION (@CHECK_MICRO_VERSION@)
-CK_DLL_EXP /*extern*/ int CK_EXPORT check_major_version;
-CK_DLL_EXP /*extern*/ int CK_EXPORT check_minor_version;
-CK_DLL_EXP /*extern*/ int CK_EXPORT check_micro_version;
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-#if defined(_MSC_VER)
-#define pid_t int
-#endif
-
-/**
- * Type for a test case
- *
- * A TCase represents a test case. Create with tcase_create, free
- * with tcase_free. For the moment, test cases can only be run
- * through a suite
-*/
-typedef struct TCase TCase;
-
-/**
- * Type for a test function
- */
-typedef void (*TFun) (int);
-
-/**
- * Type for a setup/teardown function
- */
-typedef void (*SFun) (void);
-
-/**
- * Type for a test suite
- */
-typedef struct Suite Suite;
-
-/**
- * Creates a test suite with the given name.
- *
- * Create a suite, which will contain test cases. Once
- * created, use suite_add_tcase() to add test cases.
- * When finished, create a suite runner from the
- * suite using srunner_create()
- *
- * @param name name of the suite
- *
- * @return suite
- *
- * @since 0.6.0
- */
-CK_DLL_EXP Suite *CK_EXPORT suite_create (const char *name);
-
-/**
- * Determines whether a given test suite contains a case named after a
- * given string.
- *
- * @param s suite to check
- * @param tcname test case to look for
- *
- * @return 1 iff the given test case is within the given suite;
- * 0 otherwise
- *
- * @since 0.9.9
- */
-CK_DLL_EXP int CK_EXPORT suite_tcase (Suite * s, const char *tcname);
-
-/**
- * Add a test case to a suite.
- *
- * Note that if the TCase has already been added attempting
- * to add it again will be ignored.
- *
- * @param s suite to add test case to
- * @param tc test case to add to suite
- *
- * @since 0.6.0
- */
-CK_DLL_EXP void CK_EXPORT suite_add_tcase (Suite * s, TCase * tc);
-
-/**
- * Create a test case.
- *
- * Once created, tests can be added with the tcase_add_test()
- * function, and the test case assigned to a suite with the
- * suite_add_tcase() function.
- *
- * @param name name of the test case
- *
- * @return test case containing no tests
- *
- * @since 0.6.0
- * */
-CK_DLL_EXP TCase *CK_EXPORT tcase_create (const char *name);
-
-/**
- * Associate a test case with certain tags.
- * Replaces any existing tags with the new set.
- *
- * @param tc the test case
- *
- * @param tags string containing arbitrary tags separated by spaces.
- * This will be copied. Passing NULL clears all tags.
- *
- * @since 0.11.0
- * */
-CK_DLL_EXP void CK_EXPORT tcase_set_tags (TCase * tc, const char *tags);
-/**
- * Add a test function to a test case
- *
- * @param tc test case to add test to
- * @param tf test function to add to test case
- *
- * @since 0.6.0
- * */
-#define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0)
-
-/**
- * Add a test function with signal handling to a test case
- *
- * The added test is expected to terminate by throwing the given signal
- *
- * @param tc test case to add test to
- * @param tf test function to add to test case
- * @param signal expected signal for test function to throw in order for
- * the test to be considered passing
- *
- * @since 0.9.2
- * */
-#define tcase_add_test_raise_signal(tc,tf,signal) \
- _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1)
-
-/**
- * Add a test function with an expected exit value to a test case
- *
- * The added test is expected to terminate by exiting with the given value
- *
- * @param tc test case to add test to
- * @param tf test function to add to test case
- * @param expected_exit_value exit value for test function to return in
- * order for the test to be considered passing
- *
- * @since 0.9.7
- */
-#define tcase_add_exit_test(tc, tf, expected_exit_value) \
- _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1)
-
-/**
- * Add a looping test function to a test case
- *
- * The test will be called in a for(i = s; i < e; i++) loop with each
- * iteration being executed in a new context. The loop variable 'i' is
- * available in the test.
- *
- * @param tc test case to add test to
- * @param tf function to add to test case
- * @param s starting index for value "i" in test
- * @param e ending index for value "i" in test
- *
- * @since 0.9.4
- */
-#define tcase_add_loop_test(tc,tf,s,e) \
- _tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e))
-
-/**
- * Add a looping test function with signal handling to a test case
- *
- * The test will be called in a for(i = s; i < e; i++) loop with each
- * iteration being executed in a new context. The loop variable 'i' is
- * available in the test.
- *
- * The added test is expected to terminate by throwing the given signal
- *
- * @param tc test case to add test to
- * @param tf function to add to test case
- * @param signal expected signal for test function to throw in order for
- * the test to be considered passing
- * @param s starting index for value "i" in test
- * @param e ending index for value "i" in test
- *
- * @since 0.9.5
- */
-#define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
- _tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e))
-
-/**
- * Add a looping test function with an expected exit value to a test case
- *
- * The test will be called in a for(i = s; i < e; i++) loop with each
- * iteration being executed in a new context. The loop variable 'i' is
- * available in the test.
- *
- * The added test is expected to terminate by exiting with the given value
- *
- * @param tc test case to add test to
- * @param tf function to add to test case
- * @param expected_exit_value exit value for test function to return in
- * order for the test to be considered passing
- * @param s starting index for value "i" in test
- * @param e ending index for value "i" in test
- *
- * @since 0.9.7
- */
-#define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \
- _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e))
-
-/* Add a test function to a test case
- (function version -- use this when the macro won't work
-*/
-CK_DLL_EXP void CK_EXPORT _tcase_add_test (TCase * tc, TFun tf,
- const char *fname, int _signal, int allowed_exit_value, int start, int end);
-
-/**
- * Add unchecked fixture setup/teardown functions to a test case
- *
- * Unchecked fixture functions are run at the start and end of the
- * test case, and not before and after unit tests. Further,
- * unchecked fixture functions are not run in a separate address space,
- * like test functions, and so must not exit or signal (e.g.,
- * segfault).
- *
- * Also, when run in CK_NOFORK mode, unchecked fixture functions may
- * lead to different unit test behavior if unit tests change data
- * setup by the fixture functions.
- *
- * Note that if a setup function fails, the remaining setup functions
- * will be omitted, as will the test case and the teardown functions.
- * If a teardown function fails the remaining teardown functions will be
- * omitted.
- *
- * @param tc test case to add unchecked fixture setup/teardown to
- * @param setup function to add to be executed before the test case;
- * if NULL no setup function is added
- * @param teardown function to add to be executed after the test case;
- * if NULL no teardown function is added
- * @since 0.8.0
- */
-CK_DLL_EXP void CK_EXPORT tcase_add_unchecked_fixture (TCase * tc, SFun setup,
- SFun teardown);
-
-/**
- * Add checked fixture setup/teardown functions to a test case
- *
- * Checked fixture functions are run before and after each unit test inside
- * of the address space of the test. Thus, if using CK_FORK
- * mode the separate process running the unit test will survive signals
- * or unexpected exits in the fixture function. Also, if the setup
- * function is idempotent, unit test behavior will be the same in
- * CK_FORK and CK_NOFORK modes.
- *
- * However, since fixture functions are run before and after each unit
- * test, they should not be expensive code.
- *
- * Note that if a setup function fails, the remaining setup functions
- * will be omitted, as will the test and the teardown functions. If a
- * teardown function fails the remaining teardown functions will be
- * omitted.
- *
- * @param tc test case to add checked fixture setup/teardown to
- * @param setup function to add to be executed before each unit test in
- * the test case; if NULL no setup function is added
- * @param teardown function to add to be executed after each unit test in
- * the test case; if NULL no teardown function is added
- *
- * @since 0.8.0
-*/
-CK_DLL_EXP void CK_EXPORT tcase_add_checked_fixture (TCase * tc, SFun setup,
- SFun teardown);
-
-/**
- * Set the timeout for all tests in a test case.
- *
- * A test that lasts longer than the timeout (in seconds) will be killed
- * and thus fail with an error.
- *
- * If not set, the default timeout is one assigned at compile time. If
- * the environment variable CK_DEFAULT_TIMEOUT is defined and no timeout
- * is set, the value in the environment variable is used.
- *
- * If Check is compile without fork() support this call is ignored,
- * as timeouts are not possible.
- *
- * @param tc test case to assign timeout to
- * @param timeout to use, in seconds. If the value contains a decimal
- * portion, but no high resolution timer is available,
- * the value is rounded up to the nearest second.
- *
- * @since 0.9.2
- */
-CK_DLL_EXP void CK_EXPORT tcase_set_timeout (TCase * tc, double timeout);
-
-/* Internal function to mark the start of a test function */
-CK_DLL_EXP void CK_EXPORT tcase_fn_start (const char *fname, const char *file,
- int line);
-
-/**
- * Start a unit test with START_TEST(unit_name), end with END_TEST.
- *
- * One must use braces within a START_/END_ pair to declare new variables
- *
- * @since 0.6.0
- */
-#define START_TEST(__testname)\
-static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
-{\
- tcase_fn_start (""# __testname, __FILE__, __LINE__);
-
-/**
- * End a unit test
- *
- * @since 0.6.0
- */
-#define END_TEST }
-
-/*
- * Fail the test case unless expr is false
- *
- * This call is deprecated.
- */
-#define fail_unless ck_assert_msg
-
-/*
- * Fail the test case if expr is false
- *
- * This call is deprecated.
- *
- * NOTE: The space before the comma sign before ## is essential to be compatible
- * with gcc 2.95.3 and earlier.
- * FIXME: these macros may conflict with C89 if expr is
- * FIXME: strcmp (str1, str2) due to excessive string length.
- */
-#define fail_if(expr, ...)\
- (expr) ? \
- _ck_assert_failed(__FILE__, __LINE__, "Failure '"#expr"' occurred" , ## __VA_ARGS__, NULL) \
- : _mark_point(__FILE__, __LINE__)
-
-/*
- * Fail the test
- *
- * This call is deprecated.
- */
-#define fail ck_abort_msg
-
-/*
- * This is called whenever an assertion fails.
- */
-CK_DLL_EXP void CK_EXPORT
-_ck_assert_failed (const char *file, int line, const char *expr, ...)
- CK_ATTRIBUTE_NORETURN;
-
-/**
- * Fail the test if expression is false
- *
- * @param expr expression to evaluate
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert(expr) ck_assert_msg(expr, NULL)
-
-/* The space before the comma sign before ## is essential to be compatible
- with gcc 2.95.3 and earlier.
-*/
-/**
- * Fail the test if the expression is false; print message on failure
- *
- * @param expr expression to evaluate
- * @param ... message to print (in printf format) if expression is false
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert_msg(expr, ...) \
- (expr) ? \
- _mark_point(__FILE__, __LINE__) : \
- _ck_assert_failed(__FILE__, __LINE__, "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL)
-
-/**
- * Unconditionally fail the test
- *
- * @note Once called, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_abort() ck_abort_msg(NULL)
-/**
- * Unconditionally fail the test; print a message
- *
- * @param ... message to print (in printf format)
- *
- * @note Once called, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_abort_msg(...) _ck_assert_failed(__FILE__, __LINE__, "Failed" , ## __VA_ARGS__, NULL)
-
-/* Signed and unsigned integer comparison macros with improved output compared to ck_assert(). */
-/* OP may be any comparison operator. */
-#define _ck_assert_int(X, OP, Y) do { \
- gint64 _ck_x = (X); \
- gint64 _ck_y = (Y); \
- ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: " \
- "%s==%" G_GINT64_FORMAT ", %s==%" G_GINT64_FORMAT, #X#OP#Y, #X, _ck_x, #Y, _ck_y); \
-} while (0)
-
-/**
- * Check two signed integers to determine if X==Y
- *
- * If not X==Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y)
-/**
- * Check two signed integers to determine if X!=Y
- *
- * If not X!=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert_int_ne(X, Y) _ck_assert_int(X, !=, Y)
-/**
- * Check two signed integers to determine if X<Y
- *
- * If not X<Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_int_lt(X, Y) _ck_assert_int(X, <, Y)
-/**
- * Check two signed integers to determine if X<=Y
- *
- * If not X<=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_int_le(X, Y) _ck_assert_int(X, <=, Y)
-/**
- * Check two signed integers to determine if X>Y
- *
- * If not X>Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_int_gt(X, Y) _ck_assert_int(X, >, Y)
-/**
- * Check two signed integers to determine if X>=Y
- *
- * If not X>=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_int_ge(X, Y) _ck_assert_int(X, >=, Y)
-
-#define _ck_assert_uint(X, OP, Y) do { \
- guint64 _ck_x = (X); \
- guint64 _ck_y = (Y); \
- ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: " \
- "%s==%" G_GUINT64_FORMAT ", %s==%" G_GUINT64_FORMAT, #X#OP#Y, #X, _ck_x, #Y, _ck_y); \
-} while (0)
-/**
- * Check two unsigned integers to determine if X==Y
- *
- * If not X==Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_eq(X, Y) _ck_assert_uint(X, ==, Y)
-/**
- * Check two unsigned integers to determine if X!=Y
- *
- * If not X!=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_ne(X, Y) _ck_assert_uint(X, !=, Y)
-/**
- * Check two unsigned integers to determine if X<Y
- *
- * If not X<Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_lt(X, Y) _ck_assert_uint(X, <, Y)
-/**
- * Check two unsigned integers to determine if X<=Y
- *
- * If not X<=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_le(X, Y) _ck_assert_uint(X, <=, Y)
-/**
- * Check two unsigned integers to determine if X>Y
- *
- * If not X>Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_gt(X, Y) _ck_assert_uint(X, >, Y)
-/**
- * Check two unsigned integers to determine if X>=Y
- *
- * If not X>=Y, the test fails.
- *
- * @param X signed integer
- * @param Y signed integer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_uint_ge(X, Y) _ck_assert_uint(X, >=, Y)
-
-/* String comparison macros with improved output compared to ck_assert() */
-/* OP might be any operator that can be used in '0 OP strcmp(X,Y)' comparison */
-/* The x and y parameter swap in strcmp() is needed to handle >, >=, <, <= operators */
-#define _ck_assert_str(X, OP, Y) do { \
- const char* _ck_x = (X); \
- const char* _ck_y = (Y); \
- ck_assert_msg(0 OP strcmp(_ck_y, _ck_x), \
- "Assertion '%s' failed: %s==\"%s\", %s==\"%s\"", #X#OP#Y, #X, _ck_x, #Y, _ck_y); \
-} while (0)
-/**
- * Check two strings to determine if 0==strcmp(X,Y)
- *
- * If not 0==strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert_str_eq(X, Y) _ck_assert_str(X, ==, Y)
-/**
- * Check two strings to determine if 0!=strcmp(X,Y)
- *
- * If not 0!=strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.6
- */
-#define ck_assert_str_ne(X, Y) _ck_assert_str(X, !=, Y)
-/**
- * Check two strings to determine if 0<strcmp(X,Y), (e.g. strcmp(X,Y)>0)
- *
- * If not 0<strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_str_lt(X, Y) _ck_assert_str(X, <, Y)
-/**
- * Check two strings to determine if 0<=strcmp(X,Y) (e.g. strcmp(X,Y)>=0)
- *
- * If not 0<=strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_str_le(X, Y) _ck_assert_str(X, <=, Y)
-/**
- * Check two strings to determine if 0<strcmp(X,Y) (e.g. strcmp(X,Y)>0)
- *
- * If not 0<strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_str_gt(X, Y) _ck_assert_str(X, >, Y)
-/**
- * Check two strings to determine if 0>=strcmp(X,Y) (e.g. strcmp(X,Y)<=0)
- *
- * If not 0>=strcmp(X,Y), the test fails.
- *
- * @param X string
- * @param Y string to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_str_ge(X, Y) _ck_assert_str(X, >=, Y)
-
-/* Pointer comparison macros with improved output compared to ck_assert(). */
-/* OP may only be == or != */
-#define _ck_assert_ptr(X, OP, Y) do { \
- const void* _ck_x = (X); \
- const void* _ck_y = (Y); \
- ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: %s==%#x, %s==%#x", #X#OP#Y, #X, _ck_x, #Y, _ck_y); \
-} while (0)
-
-/**
- * Check if two pointers are equal.
- *
- * If the two passed pointers are not equal, the test
- * fails.
- *
- * @param X pointer
- * @param Y pointer to compare against X
- *
- * @note If the check fails, the remaining of the test is aborted
- *
- * @since 0.9.10
- */
-#define ck_assert_ptr_eq(X, Y) _ck_assert_ptr(X, ==, Y)
-
-/**
- * Check if two pointers are not.
- *
- * If the two passed pointers are equal, the test fails.
- *
- * @param X pointer
- * @param Y pointer to compare against X
- *
- * @since 0.9.10
- */
-#define ck_assert_ptr_ne(X, Y) _ck_assert_ptr(X, !=, Y)
-
-/**
- * Mark the last point reached in a unit test.
- *
- * If the test throws a signal or exits, the location noted with the
- * failure is the last location of a ck_assert*() or ck_abort() call.
- * Use mark_point() to record intermediate locations (useful for tracking down
- * crashes or exits).
- *
- * @since 0.6.0
-*/
-#define mark_point() _mark_point(__FILE__,__LINE__)
-
-/* Non macro version of #mark_point */
-CK_DLL_EXP void CK_EXPORT _mark_point (const char *file, int line);
-
-/**
- * Enum describing the possible results of a test
- */
-enum test_result
-{
- CK_TEST_RESULT_INVALID, /**< Default value; should not encounter this */
- CK_PASS, /**< Test passed */
- CK_FAILURE, /**< Test completed but failed */
- CK_ERROR /**< Test failed to complete
- (unexpected signal or non-zero early exit) */
-};
-
-/**
- * Enum specifying the verbosity of output a SRunner should produce
- */
-enum print_output
-{
- CK_SILENT, /**< No output */
- CK_MINIMAL, /**< Only summary output */
- CK_NORMAL, /**< All failed tests */
- CK_VERBOSE, /**< All tests */
- CK_ENV, /**< Look at environment var CK_VERBOSITY
- for what verbosity to use, which can be
- either "silent", "minimal", "normal",
- or "verbose". If the environment variable
- is not set, then CK_NORMAL will be used.*/
-#if @ENABLE_SUBUNIT@
- CK_SUBUNIT, /**< Run as a subunit child process */
-#endif
- CK_LAST /**< Not a valid option */
-};
-
-/**
- * Holds state for a running of a test suite
- */
-typedef struct SRunner SRunner;
-
-/**
- * Opaque type for a test failure
- */
-typedef struct TestResult TestResult;
-
-/**
- * Enum representing the types of contexts for a test
- */
-enum ck_result_ctx
-{
- CK_CTX_INVALID, /**< Default value; should not encounter this */
- CK_CTX_SETUP, /**< Setup before a test */
- CK_CTX_TEST, /**< Body of test itself */
- CK_CTX_TEARDOWN /**< Teardown after a test */
-};
-
-/**
- * Retrieve type of result that the given test result represents.
- *
- * This is a member of test_result, and can represent a
- * pass, failure, or error.
- *
- * @param tr test result to retrieve result from
- *
- * @return result of given test
- *
- * @since 0.6.0
- */
-CK_DLL_EXP int CK_EXPORT tr_rtype (TestResult * tr);
-
-/**
- * Retrieve context in which the result occurred for the given test result.
- *
- * The types of contents include the test setup, teardown, or the
- * body of the test itself.
- *
- * @param tr test result to retrieve context from
- *
- * @return context to which the given test result applies
- *
- * @since 0.8.0
- */
-CK_DLL_EXP enum ck_result_ctx CK_EXPORT tr_ctx (TestResult * tr);
-
-/**
- * Retrieve failure message from test result, if applicable.
- *
- * @return pointer to a message, if one exists. NULL otherwise.
- *
- * @since 0.6.0
- */
-CK_DLL_EXP const char *CK_EXPORT tr_msg (TestResult * tr);
-
-/**
- * Retrieve line number at which a failure occurred, if applicable.
- *
- * @return If the test resulted in a failure, returns the line number
- * that the failure occurred on; otherwise returns -1.
- *
- * @since 0.6.0
- */
-CK_DLL_EXP int CK_EXPORT tr_lno (TestResult * tr);
-
-/**
- * Retrieve file name at which a failure occurred, if applicable.
- *
- * @return If the test resulted in a failure, returns a string
- * containing the name of the file where the failure
- * occurred; otherwise returns NULL.
- *
- * @since 0.6.0
- */
-CK_DLL_EXP const char *CK_EXPORT tr_lfile (TestResult * tr);
-
-/**
- * Retrieve test case name in which a failure occurred, if applicable.
- *
- * @return If the test resulted in a failure, returns a string
- * containing the name of the test suite where the failure
- * occurred; otherwise returns NULL.
- *
- * @since 0.6.0
- */
-CK_DLL_EXP const char *CK_EXPORT tr_tcname (TestResult * tr);
-
-/**
- * Creates a suite runner for the given suite.
- *
- * Once created, additional suites can be added to the
- * suite runner using srunner_add_suite(), and the suite runner can be
- * run with srunner_run_all(). Once finished, the suite runner
- * must be freed with srunner_free().
- *
- * @param s suite to generate a suite runner for
- *
- * @return suite runner for the given suite
- *
- * @since 0.6.0
- */
-CK_DLL_EXP SRunner *CK_EXPORT srunner_create (Suite * s);
-
-/**
- * Add an additional suite to a suite runner.
- *
- * The first suite in a suite runner is always added in srunner_create().
- * This call adds additional suites to a suite runner.
- *
- * @param sr suite runner to add the given suite
- * @param s suite to add to the given suite runner
- *
- * @since 0.7.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_add_suite (SRunner * sr, Suite * s);
-
-/**
- * Frees a suite runner, including all contained suite and test cases.
- *
- * This call is responsible for freeing all resources related to a
- * suite runner and all contained suites and test cases. Suite and
- * test cases need not be freed individually, as this call handles that.
- *
- * @param sr suite runner to free
- *
- * @since 0.6.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_free (SRunner * sr);
-
-/**
- * Runs a suite runner and all contained suite, printing results to
- * stdout as specified by the print_mode.
- *
- * In addition to running all suites, if the suite runner has been
- * configured to output to a log, that is also performed.
- *
- * Note that if the CK_RUN_CASE, CK_RUN_SUITE, CK_INCLUDE_TAGS and/or
- * CK_EXCLUDE_TAGS environment variables are defined, then only the
- * named suites or test cases will run.
- *
- * @param sr suite runner to run all suites from
- * @param print_mode the verbosity in which to report results to stdout
- *
- * @since 0.6.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_run_all (SRunner * sr,
- enum print_output print_mode);
-
-/**
- * Run a specific suite or test case from a suite runner, printing results
- * to stdout as specified by the print_mode.
- *
- * In addition to running any applicable suites or test cases, if the
- * suite runner has been configured to output to a log, that is also
- * performed.
- *
- * Note that if the sname and tcname parameters are passed as null
- * then the function will fallback to using the environment variables
- * CK_RUN_SUITE and CK_RUN_CASE respectively in order to select the
- * suite/cases.
- *
- * Similarly if the CK_INCLUDE_TAGS and/or CK_EXCLUDE_TAGS environment
- * variables are defined then these will further filter the test cases
- * (see srunner_run_tagged, below).
- *
- * @param sr suite runner where the given suite or test case must be
- * @param sname suite name to run. A NULL means use the value of the
- * environment variable CK_RUN_SUITE if set, otherwise run "any/every
- * suite".
- * @param tcname test case name to run. A NULL means use the value of
- * the environment variable CK_RUN_CASE if set, otherwise run
- * "any/every case".
- * @param print_mode the verbosity in which to report results to stdout
- *
- * @since 0.9.9
- */
-CK_DLL_EXP void CK_EXPORT srunner_run (SRunner * sr, const char *sname,
- const char *tcname, enum print_output print_mode);
-
-
-/**
- * Run a specific suite or test case or testcases with specific tags
- * from a suite runner, printing results to stdout as specified by the
- * print_mode.
- *
- * In addition to running any applicable suites or test cases, if the
- * suite runner has been configured to output to a log, that is also
- * performed.
- *
- * Note that if sname, tcname, include_tags, exclude_tags parameters
- * are passed as NULL then if the environment variables CK_RUN_SUITE,
- * CK_RUN_CASE, CK_INCLUDE_TAGS, CK_EXCLUDE_TAGS are defined then these
- * values will be used instead.
- *
- * @param sr suite runner where the given suite or test case must be
- * @param sname suite name to run. A NULL means use the value of the
- * environment variable CK_RUN_SUITE if set, otherwise run "any/every
- * suite".
- * @param tcname test case name to run. A NULL means use the value of
- * the environment variable CK_RUN_CASE if set, otherwise run
- * "any/every case".
- * @param include_tags space separate list of tags. Only run test
- * cases that share one of these tags. A NULL means use the value of
- * the environment variable CK_INCLUDE_TAGS if set, otherwise run
- * "any/every test case".
- * @param exclude_tags space separate list of tags. Only run test
- * cases that do not share one of these tags even if they are selected
- * by an included tag. A NULL means use the value of the environment
- * variable CK_EXCLUDE_TAGS if set, otherwise run "any/every test
- * case".
- * @param print_mode the verbosity in which to report results to stdout
- *
- * @since 0.11.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_run_tagged (SRunner * sr, const char *sname,
- const char *tcname,
- const char *include_tags,
- const char *exclude_tags, enum print_output print_mode);
-
-/**
- * Retrieve the number of failed tests executed by a suite runner.
- *
- * This value represents both test failures and errors.
- *
- * @param sr suite runner to query for all failed tests
- *
- * @return number of test failures and errors found by the suite runner
- *
- * @since 0.6.1
- */
-CK_DLL_EXP int CK_EXPORT srunner_ntests_failed (SRunner * sr);
-
-/**
- * Retrieve the total number of tests run by a suite runner.
- *
- * @param sr suite runner to query for all tests run
- *
- * @return number of all tests run by the suite runner
- *
- * @since 0.6.1
- */
-CK_DLL_EXP int CK_EXPORT srunner_ntests_run (SRunner * sr);
-
-/**
- * Return an array of results for all failures found by a suite runner.
- *
- * Number of results is equal to srunner_nfailed_tests().
- *
- * Information about individual results can be queried using:
- * tr_rtype(), tr_ctx(), tr_msg(), tr_lno(), tr_lfile(), and tr_tcname().
- *
- * Memory is malloc'ed and must be freed; however free the entire structure
- * instead of individual test cases.
- *
- * @param sr suite runner to retrieve results from
- *
- * @return array of TestResult objects
- *
- * @since 0.6.0
- */
-CK_DLL_EXP TestResult **CK_EXPORT srunner_failures (SRunner * sr);
-
-/**
- * Return an array of results for all tests run by a suite runner.
- *
- * Number of results is equal to srunner_ntests_run(), and excludes
- * failures due to setup function failure.
- *
- * Information about individual results can be queried using:
- * tr_rtype(), tr_ctx(), tr_msg(), tr_lno(), tr_lfile(), and tr_tcname().
- *
- * Memory is malloc'ed and must be freed; however free the entire structure
- * instead of individual test cases.
- *
- * @param sr suite runner to retrieve results from
- *
- * @return array of TestResult objects
- *
- * @since 0.6.1
-*/
-CK_DLL_EXP TestResult **CK_EXPORT srunner_results (SRunner * sr);
-
-/**
- * Print the results contained in an SRunner to stdout.
- *
- * @param sr suite runner to print results for to stdout
- * @param print_mode the print_output (verbosity) to use to report
- * the result
- *
- * @since 0.7.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_print (SRunner * sr,
- enum print_output print_mode);
-
-/**
- * Set the suite runner to output the result in log format to the
- * given file.
- *
- * Note: log file setting is an initialize only operation -- it should
- * be done immediately after SRunner creation, and the log file can't be
- * changed after being set.
- *
- * This setting does not conflict with the other log output types;
- * all logging types can occur concurrently if configured.
- *
- * @param sr suite runner to log results of in log format
- * @param fname file name to output log results to
- *
- * @since 0.7.1
-*/
-CK_DLL_EXP void CK_EXPORT srunner_set_log (SRunner * sr, const char *fname);
-
-/**
- * Checks if the suite runner is assigned a file for log output.
- *
- * @param sr suite runner to check
- *
- * @return 1 iff the suite runner currently is configured to output
- * in log format; 0 otherwise
- *
- * @since 0.7.1
- */
-CK_DLL_EXP int CK_EXPORT srunner_has_log (SRunner * sr);
-
-/**
- * Retrieves the name of the currently assigned file
- * for log output, if any exists.
- *
- * @return the name of the log file, or NULL if none is configured
- *
- * @since 0.7.1
- */
-CK_DLL_EXP const char *CK_EXPORT srunner_log_fname (SRunner * sr);
-
-/**
- * Set the suite runner to output the result in XML format to the
- * given file.
- *
- * Note: XML file setting is an initialize only operation -- it should
- * be done immediately after SRunner creation, and the XML file can't be
- * changed after being set.
- *
- * This setting does not conflict with the other log output types;
- * all logging types can occur concurrently if configured.
- *
- * @param sr suite runner to log results of in XML format
- * @param fname file name to output XML results to
- *
- * @since 0.9.1
-*/
-CK_DLL_EXP void CK_EXPORT srunner_set_xml (SRunner * sr, const char *fname);
-
-/**
- * Checks if the suite runner is assigned a file for XML output.
- *
- * @param sr suite runner to check
- *
- * @return 1 iff the suite runner currently is configured to output
- * in XML format; 0 otherwise
- *
- * @since 0.9.1
- */
-CK_DLL_EXP int CK_EXPORT srunner_has_xml (SRunner * sr);
-
-/**
- * Retrieves the name of the currently assigned file
- * for XML output, if any exists.
- *
- * @return the name of the XML file, or NULL if none is configured
- *
- * @since 0.9.1
- */
-CK_DLL_EXP const char *CK_EXPORT srunner_xml_fname (SRunner * sr);
-
-/**
- * Set the suite runner to output the result in TAP format to the
- * given file.
- *
- * Note: TAP file setting is an initialize only operation -- it should
- * be done immediately after SRunner creation, and the TAP file can't be
- * changed after being set.
- *
- * This setting does not conflict with the other log output types;
- * all logging types can occur concurrently if configured.
- *
- * @param sr suite runner to log results of in TAP format
- * @param fname file name to output TAP results to
- *
- * @since 0.9.12
-*/
-CK_DLL_EXP void CK_EXPORT srunner_set_tap (SRunner * sr, const char *fname);
-
-/**
- * Checks if the suite runner is assigned a file for TAP output.
- *
- * @param sr suite runner to check
- *
- * @return 1 iff the suite runner currently is configured to output
- * in TAP format; 0 otherwise
- *
- * @since 0.9.12
- */
-CK_DLL_EXP int CK_EXPORT srunner_has_tap (SRunner * sr);
-
-/**
- * Retrieves the name of the currently assigned file
- * for TAP output, if any exists.
- *
- * @return the name of the TAP file, or NULL if none is configured
- *
- * @since 0.9.12
- */
-CK_DLL_EXP const char *CK_EXPORT srunner_tap_fname (SRunner * sr);
-
-/**
- * Enum describing the current fork usage.
- */
-enum fork_status
-{
- CK_FORK_GETENV, /**< look in the environment for CK_FORK */
- CK_FORK, /**< call fork to run tests */
- CK_NOFORK /**< don't call fork */
-};
-
-/**
- * Retrieve the current fork status for the given suite runner
- *
- * @param sr suite runner to check fork status of
- *
- * @since 0.8.0
- */
-CK_DLL_EXP enum fork_status CK_EXPORT srunner_fork_status (SRunner * sr);
-
-/**
- * Set the fork status for a given suite runner.
- *
- * The default fork status is CK_FORK_GETENV, which will look
- * for the CK_FORK environment variable, which can be set to
- * "yes" or "no". If the environment variable is not present,
- * CK_FORK will be used if fork() is available on the system,
- * otherwise CK_NOFORK is used.
- *
- * If set to CK_FORK or CK_NOFORK, the environment variable
- * if defined is ignored.
- *
- * If Check is compiled without support for fork(), attempting
- * to set the status to CK_FORK is ignored.
- *
- * @param sr suite runner to assign the fork status to
- * @param fstat fork status to assign
- *
- * @since 0.8.0
- */
-CK_DLL_EXP void CK_EXPORT srunner_set_fork_status (SRunner * sr,
- enum fork_status fstat);
-
-/**
- * Invoke fork() during a test and assign the child to the same
- * process group that the rest of the test case uses.
- *
- * One can invoke fork() directly during a test; however doing so
- * may not guarantee that any children processes are destroyed once
- * the test finishes. Once a test has completed, all processes in
- * the process group will be killed; using this wrapper will prevent
- * orphan processes.
- *
- * If Check is compiled without fork() support this call simply
- * return -1 and does nothing.
- *
- * @return On success, the PID of the child process is returned in
- * the parent, and 0 is returned in the child. On failure,
- * a value of -1 is returned to the parent process and no
- * child process is created.
- *
- * @since 0.9.3
- */
-#if !defined(_MSC_VER)
-CK_DLL_EXP pid_t CK_EXPORT check_fork (void);
-#endif
-
-/**
- * Wait for the pid and exit.
- *
- * This is to be used in conjunction with check_fork(). When called,
- * will wait for the given process to terminate. If the process
- * exited without error, exit(EXIT_SUCCESS) is invoked; otherwise
- * exit(EXIT_FAILURE) is invoked.
- *
- * If Check is compiled without support for fork(), this invokes
- * exit(EXIT_FAILURE).
- *
- * @param pid process to wait for, created by check_fork()
- *
- * @since 0.9.3
- */
-#if !defined(_MSC_VER)
-CK_DLL_EXP void CK_EXPORT
-check_waitpid_and_exit (pid_t pid)
- CK_ATTRIBUTE_NORETURN;
-#endif
-
-#ifdef __cplusplus
-CK_CPPEND
-#endif
-#endif /* CHECK_H */
diff --git a/libs/gst/check/libcheck/check_error.c b/libs/gst/check/libcheck/check_error.c
deleted file mode 100644
index 8f293aa77e..0000000000
--- a/libs/gst/check/libcheck/check_error.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-
-#include "check_error.h"
-
-/**
- * Storage for setjmp/longjmp context information used in NOFORK mode
- */
-jmp_buf error_jmp_buffer;
-
-
-/* FIXME: including a colon at the end is a bad way to indicate an error */
-void
-eprintf (const char *fmt, const char *file, int line, ...)
-{
- va_list args;
-
- fflush (stderr);
-
- fprintf (stderr, "%s:%d: ", file, line);
- va_start (args, line);
- vfprintf (stderr, fmt, args);
- va_end (args);
-
- /*include system error information if format ends in colon */
- if (fmt[0] != '\0' && fmt[strlen (fmt) - 1] == ':')
- fprintf (stderr, " %s", strerror (errno));
- fprintf (stderr, "\n");
-
- exit (2);
-}
-
-void *
-emalloc (size_t n)
-{
- void *p;
-
- p = malloc (n);
- if (p == NULL)
- eprintf ("malloc of %u bytes failed:", __FILE__, __LINE__ - 2, n);
- return p;
-}
-
-void *
-erealloc (void *ptr, size_t n)
-{
- void *p;
-
- p = realloc (ptr, n);
- if (p == NULL)
- eprintf ("realloc of %u bytes failed:", __FILE__, __LINE__ - 2, n);
- return p;
-}
diff --git a/libs/gst/check/libcheck/check_error.h b/libs/gst/check/libcheck/check_error.h
deleted file mode 100644
index f325fc69c9..0000000000
--- a/libs/gst/check/libcheck/check_error.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef ERROR_H
-#define ERROR_H
-
-#include "libcompat/libcompat.h"
-#include <setjmp.h>
-
-extern jmp_buf error_jmp_buffer;
-
-/* Include stdlib.h beforehand */
-
-/* Print error message and die
- If fmt ends in colon, include system error information */
-void
-eprintf (const char *fmt, const char *file, int line, ...)
- CK_ATTRIBUTE_NORETURN;
-/* malloc or die */
- void *emalloc (size_t n);
- void *erealloc (void *, size_t n);
-
-#endif /*ERROR_H */
diff --git a/libs/gst/check/libcheck/check_impl.h b/libs/gst/check/libcheck/check_impl.h
deleted file mode 100644
index 420543e2ef..0000000000
--- a/libs/gst/check/libcheck/check_impl.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_IMPL_H
-#define CHECK_IMPL_H
-
-/* This header should be included by any module that needs
- to know the implementation details of the check structures
- Include stdio.h, time.h, & list.h before this header
-*/
-
-#define US_PER_SEC 1000000
-#define NANOS_PER_SECONDS 1000000000
-
-/** calculate the difference in useconds out of two "struct timespec"s */
-#define DIFF_IN_USEC(begin, end) \
- ( (((end).tv_sec - (begin).tv_sec) * US_PER_SEC) + \
- ((end).tv_nsec/1000) - ((begin).tv_nsec/1000) )
-
-typedef struct TF
-{
- TFun fn;
- int loop_start;
- int loop_end;
- const char *name;
- int signal;
- signed char allowed_exit_value;
-} TF;
-
-struct Suite
-{
- const char *name;
- List *tclst; /* List of test cases */
-};
-
-typedef struct Fixture
-{
- int ischecked;
- SFun fun;
-} Fixture;
-
-struct TCase
-{
- const char *name;
- struct timespec timeout;
- List *tflst; /* list of test functions */
- List *unch_sflst;
- List *unch_tflst;
- List *ch_sflst;
- List *ch_tflst;
- List *tags;
-};
-
-typedef struct TestStats
-{
- int n_checked;
- int n_failed;
- int n_errors;
-} TestStats;
-
-struct TestResult
-{
- enum test_result rtype; /* Type of result */
- enum ck_result_ctx ctx; /* When the result occurred */
- char *file; /* File where the test occurred */
- int line; /* Line number where the test occurred */
- int iter; /* The iteration value for looping tests */
- int duration; /* duration of this test in microseconds */
- const char *tcname; /* Test case that generated the result */
- const char *tname; /* Test that generated the result */
- char *msg; /* Failure message */
-};
-
-TestResult *tr_create (void);
-void tr_reset (TestResult * tr);
-void tr_free (TestResult * tr);
-
-enum cl_event
-{
- CLINITLOG_SR, /* Initialize log file */
- CLENDLOG_SR, /* Tests are complete */
- CLSTART_SR, /* Suite runner start */
- CLSTART_S, /* Suite start */
- CLEND_SR, /* Suite runner end */
- CLEND_S, /* Suite end */
- CLSTART_T, /* A test case is about to run */
- CLEND_T /* Test case end */
-};
-
-typedef void (*LFun) (SRunner *, FILE *, enum print_output,
- void *, enum cl_event);
-
-typedef struct Log
-{
- FILE *lfile;
- LFun lfun;
- int close;
- enum print_output mode;
-} Log;
-
-struct SRunner
-{
- List *slst; /* List of Suite objects */
- TestStats *stats; /* Run statistics */
- List *resultlst; /* List of unit test results */
- const char *log_fname; /* name of log file */
- const char *xml_fname; /* name of xml output file */
- const char *tap_fname; /* name of tap output file */
- List *loglst; /* list of Log objects */
- enum fork_status fstat; /* controls if suites are forked or not
- NOTE: Don't use this value directly,
- instead use srunner_fork_status */
-};
-
-
-void set_fork_status (enum fork_status fstat);
-enum fork_status cur_fork_status (void);
-
-clockid_t check_get_clockid (void);
-
-unsigned int tcase_matching_tag (TCase * tc, List * check_for);
-List *tag_string_to_list (const char *tags_string);
-
-#endif /* CHECK_IMPL_H */
diff --git a/libs/gst/check/libcheck/check_list.c b/libs/gst/check/libcheck/check_list.c
deleted file mode 100644
index 610a1250eb..0000000000
--- a/libs/gst/check/libcheck/check_list.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "check_list.h"
-#include "check_error.h"
-
-
-enum
-{
- LINIT = 1,
- LGROW = 2
-};
-
-struct List
-{
- unsigned int n_elts;
- unsigned int max_elts;
- int current; /* pointer to the current node */
- int last; /* pointer to the node before END */
- void **data;
-};
-
-static void
-maybe_grow (List * lp)
-{
- if (lp->n_elts >= lp->max_elts) {
- lp->max_elts *= LGROW;
- lp->data =
- (void **) erealloc (lp->data, lp->max_elts * sizeof (lp->data[0]));
- }
-}
-
-List *
-check_list_create (void)
-{
- List *lp;
-
- lp = (List *) emalloc (sizeof (List));
- lp->n_elts = 0;
- lp->max_elts = LINIT;
- lp->data = (void **) emalloc (sizeof (lp->data[0]) * LINIT);
- lp->current = lp->last = -1;
- return lp;
-}
-
-void
-check_list_add_front (List * lp, void *val)
-{
- if (lp == NULL)
- return;
- maybe_grow (lp);
- memmove (lp->data + 1, lp->data, lp->n_elts * sizeof lp->data[0]);
- lp->last++;
- lp->n_elts++;
- lp->current = 0;
- lp->data[lp->current] = val;
-}
-
-void
-check_list_add_end (List * lp, void *val)
-{
- if (lp == NULL)
- return;
- maybe_grow (lp);
- lp->last++;
- lp->n_elts++;
- lp->current = lp->last;
- lp->data[lp->current] = val;
-}
-
-int
-check_list_at_end (List * lp)
-{
- if (lp->current == -1)
- return 1;
- else
- return (lp->current > lp->last);
-}
-
-void
-check_list_front (List * lp)
-{
- if (lp->current == -1)
- return;
- lp->current = 0;
-}
-
-
-void
-check_list_free (List * lp)
-{
- if (lp == NULL)
- return;
-
- free (lp->data);
- free (lp);
-}
-
-void *
-check_list_val (List * lp)
-{
- if (lp == NULL)
- return NULL;
- if (lp->current == -1 || lp->current > lp->last)
- return NULL;
-
- return lp->data[lp->current];
-}
-
-void
-check_list_advance (List * lp)
-{
- if (lp == NULL)
- return;
- if (check_list_at_end (lp))
- return;
- lp->current++;
-}
-
-
-void
-check_list_apply (List * lp, void (*fp) (void *))
-{
- if (lp == NULL || fp == NULL)
- return;
-
- for (check_list_front (lp); !check_list_at_end (lp); check_list_advance (lp))
- fp (check_list_val (lp));
-
-}
-
-bool
-check_list_contains (List * lp, void *val)
-{
- for (check_list_front (lp); !check_list_at_end (lp); check_list_advance (lp)) {
- if (check_list_val (lp) == val) {
- return true;
- }
- }
-
- return false;
-}
diff --git a/libs/gst/check/libcheck/check_list.h b/libs/gst/check/libcheck/check_list.h
deleted file mode 100644
index 005361e4ff..0000000000
--- a/libs/gst/check/libcheck/check_list.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_LIST_H
-#define CHECK_LIST_H
-
-#include <stdbool.h>
-
-typedef struct List List;
-
-/* Create an empty list */
-List *check_list_create (void);
-
-/* Is list at end? */
-int check_list_at_end (List * lp);
-
-/* Position list at front */
-void check_list_front (List * lp);
-
-/* Add a value to the front of the list,
- positioning newly added value as current value.
- More expensive than list_add_end, as it uses memmove. */
-void check_list_add_front (List * lp, void *val);
-
-/* Add a value to the end of the list,
- positioning newly added value as current value */
-void check_list_add_end (List * lp, void *val);
-
-/* Give the value of the current node */
-void *check_list_val (List * lp);
-
-/* Position the list at the next node */
-void check_list_advance (List * lp);
-
-/* Free a list, but don't free values */
-void check_list_free (List * lp);
-
-void check_list_apply (List * lp, void (*fp) (void *));
-
-/* Return true if the list contains the value, false otherwise */
-bool check_list_contains (List * lp, void *val);
-
-
-#endif /* CHECK_LIST_H */
diff --git a/libs/gst/check/libcheck/check_log.c b/libs/gst/check/libcheck/check_log.c
deleted file mode 100644
index bb81d6bd0c..0000000000
--- a/libs/gst/check/libcheck/check_log.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <internal-check.h>
-#if ENABLE_SUBUNIT
-#include <subunit/child.h>
-#endif
-
-#include "check_error.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_log.h"
-#include "check_print.h"
-#include "check_str.h"
-
-/*
- * If a log file is specified to be "-", then instead of
- * opening a file the log output is printed to stdout.
- */
-#define STDOUT_OVERRIDE_LOG_FILE_NAME "-"
-
-static void srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt);
-
-void
-srunner_set_log (SRunner * sr, const char *fname)
-{
- if (sr->log_fname)
- return;
- sr->log_fname = fname;
-}
-
-int
-srunner_has_log (SRunner * sr)
-{
- return srunner_log_fname (sr) != NULL;
-}
-
-const char *
-srunner_log_fname (SRunner * sr)
-{
- /* check if log filename have been set explicitly */
- if (sr->log_fname != NULL)
- return sr->log_fname;
-
- return getenv ("CK_LOG_FILE_NAME");
-}
-
-
-void
-srunner_set_xml (SRunner * sr, const char *fname)
-{
- if (sr->xml_fname)
- return;
- sr->xml_fname = fname;
-}
-
-int
-srunner_has_xml (SRunner * sr)
-{
- return srunner_xml_fname (sr) != NULL;
-}
-
-const char *
-srunner_xml_fname (SRunner * sr)
-{
- /* check if XML log filename have been set explicitly */
- if (sr->xml_fname != NULL) {
- return sr->xml_fname;
- }
-
- return getenv ("CK_XML_LOG_FILE_NAME");
-}
-
-void
-srunner_set_tap (SRunner * sr, const char *fname)
-{
- if (sr->tap_fname)
- return;
- sr->tap_fname = fname;
-}
-
-int
-srunner_has_tap (SRunner * sr)
-{
- return srunner_tap_fname (sr) != NULL;
-}
-
-const char *
-srunner_tap_fname (SRunner * sr)
-{
- /* check if tap log filename have been set explicitly */
- if (sr->tap_fname != NULL) {
- return sr->tap_fname;
- }
-
- return getenv ("CK_TAP_LOG_FILE_NAME");
-}
-
-void
-srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
- LFun lfun, enum print_output printmode)
-{
- Log *l = (Log *) emalloc (sizeof (Log));
-
- if (printmode == CK_ENV) {
- printmode = get_env_printmode ();
- }
-
- l->lfile = lfile;
- l->lfun = lfun;
- l->close = close;
- l->mode = printmode;
- check_list_add_end (sr->loglst, l);
- return;
-}
-
-void
-log_srunner_start (SRunner * sr)
-{
- srunner_send_evt (sr, NULL, CLSTART_SR);
-}
-
-void
-log_srunner_end (SRunner * sr)
-{
- srunner_send_evt (sr, NULL, CLEND_SR);
-}
-
-void
-log_suite_start (SRunner * sr, Suite * s)
-{
- srunner_send_evt (sr, s, CLSTART_S);
-}
-
-void
-log_suite_end (SRunner * sr, Suite * s)
-{
- srunner_send_evt (sr, s, CLEND_S);
-}
-
-void
-log_test_start (SRunner * sr, TCase * tc, TF * tfun)
-{
- char buffer[100];
-
- snprintf (buffer, 99, "%s:%s", tc->name, tfun->name);
- srunner_send_evt (sr, buffer, CLSTART_T);
-}
-
-void
-log_test_end (SRunner * sr, TestResult * tr)
-{
- srunner_send_evt (sr, tr, CLEND_T);
-}
-
-static void
-srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt)
-{
- List *l;
- Log *lg;
-
- l = sr->loglst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- lg = (Log *) check_list_val (l);
- fflush (lg->lfile);
- lg->lfun (sr, lg->lfile, lg->mode, obj, evt);
- fflush (lg->lfile);
- }
-}
-
-void
-stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
- void *obj, enum cl_event evt)
-{
- Suite *s;
-
- switch (evt) {
- case CLINITLOG_SR:
- break;
- case CLENDLOG_SR:
- break;
- case CLSTART_SR:
- if (printmode > CK_SILENT) {
- fprintf (file, "Running suite(s):");
- }
- break;
- case CLSTART_S:
- s = (Suite *) obj;
- if (printmode > CK_SILENT) {
- fprintf (file, " %s\n", s->name);
- }
- break;
- case CLEND_SR:
- if (printmode > CK_SILENT) {
- /* we don't want a newline before printing here, newlines should
- come after printing a string, not before. it's better to add
- the newline above in CLSTART_S.
- */
- srunner_fprint (file, sr, printmode);
- }
- break;
- case CLEND_S:
- break;
- case CLSTART_T:
- break;
- case CLEND_T:
- break;
- default:
- eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__);
- }
-
-
-}
-
-void
-lfile_lfun (SRunner * sr, FILE * file,
- enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
- enum cl_event evt)
-{
- TestResult *tr;
- Suite *s;
-
- switch (evt) {
- case CLINITLOG_SR:
- break;
- case CLENDLOG_SR:
- break;
- case CLSTART_SR:
- break;
- case CLSTART_S:
- s = (Suite *) obj;
- fprintf (file, "Running suite %s\n", s->name);
- break;
- case CLEND_SR:
- fprintf (file, "Results for all suites run:\n");
- srunner_fprint (file, sr, CK_MINIMAL);
- break;
- case CLEND_S:
- break;
- case CLSTART_T:
- break;
- case CLEND_T:
- tr = (TestResult *) obj;
- tr_fprint (file, tr, CK_VERBOSE);
- break;
- default:
- eprintf ("Bad event type received in lfile_lfun", __FILE__, __LINE__);
- }
-
-
-}
-
-void
-xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
- enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
- enum cl_event evt)
-{
- TestResult *tr;
- Suite *s;
- static struct timespec ts_start = { 0, 0 };
- static char t[sizeof "yyyy-mm-dd hh:mm:ss"] = { 0 };
-
- if (t[0] == 0) {
- struct timeval inittv;
- struct tm now;
-
- gettimeofday (&inittv, NULL);
- clock_gettime (check_get_clockid (), &ts_start);
- if (localtime_r ((const time_t *) &(inittv.tv_sec), &now) != NULL) {
- strftime (t, sizeof ("yyyy-mm-dd hh:mm:ss"), "%Y-%m-%d %H:%M:%S", &now);
- }
- }
-
- switch (evt) {
- case CLINITLOG_SR:
- fprintf (file, "<?xml version=\"1.0\"?>\n");
- fprintf (file,
- "<?xml-stylesheet type=\"text/xsl\" href=\"http://check.sourceforge.net/xml/check_unittest.xslt\"?>\n");
- fprintf (file,
- "<testsuites xmlns=\"http://check.sourceforge.net/ns\">\n");
- fprintf (file, " <datetime>%s</datetime>\n", t);
- break;
- case CLENDLOG_SR:
- {
- struct timespec ts_end = { 0, 0 };
- unsigned long duration;
-
- /* calculate time the test were running */
- clock_gettime (check_get_clockid (), &ts_end);
- duration = (unsigned long) DIFF_IN_USEC (ts_start, ts_end);
- fprintf (file, " <duration>%lu.%06lu</duration>\n",
- duration / US_PER_SEC, duration % US_PER_SEC);
- fprintf (file, "</testsuites>\n");
- }
- break;
- case CLSTART_SR:
- break;
- case CLSTART_S:
- s = (Suite *) obj;
- fprintf (file, " <suite>\n");
- fprintf (file, " <title>");
- fprint_xml_esc (file, s->name);
- fprintf (file, "</title>\n");
- break;
- case CLEND_SR:
- break;
- case CLEND_S:
- fprintf (file, " </suite>\n");
- break;
- case CLSTART_T:
- break;
- case CLEND_T:
- tr = (TestResult *) obj;
- tr_xmlprint (file, tr, CK_VERBOSE);
- break;
- default:
- eprintf ("Bad event type received in xml_lfun", __FILE__, __LINE__);
- }
-
-}
-
-void
-tap_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
- enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
- enum cl_event evt)
-{
- TestResult *tr;
-
- static int num_tests_run = 0;
-
- switch (evt) {
- case CLINITLOG_SR:
- /* As this is a new log file, reset the number of tests executed */
- num_tests_run = 0;
- break;
- case CLENDLOG_SR:
- /* Output the test plan as the last line */
- fprintf (file, "1..%d\n", num_tests_run);
- fflush (file);
- break;
- case CLSTART_SR:
- break;
- case CLSTART_S:
- break;
- case CLEND_SR:
- break;
- case CLEND_S:
- break;
- case CLSTART_T:
- break;
- case CLEND_T:
- /* Print the test result to the tap file */
- num_tests_run += 1;
- tr = (TestResult *) obj;
- fprintf (file, "%s %d - %s:%s:%s: %s\n",
- tr->rtype == CK_PASS ? "ok" : "not ok", num_tests_run,
- tr->file, tr->tcname, tr->tname, tr->msg);
- fflush (file);
- break;
- default:
- eprintf ("Bad event type received in tap_lfun", __FILE__, __LINE__);
- }
-}
-
-#if ENABLE_SUBUNIT
-void
-subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
- void *obj, enum cl_event evt)
-{
- TestResult *tr;
- char const *name;
-
- /* assert(printmode == CK_SUBUNIT); */
-
- switch (evt) {
- case CLINITLOG_SR:
- break;
- case CLENDLOG_SR:
- break;
- case CLSTART_SR:
- break;
- case CLSTART_S:
- break;
- case CLEND_SR:
- if (printmode > CK_SILENT) {
- fprintf (file, "\n");
- srunner_fprint (file, sr, printmode);
- }
- break;
- case CLEND_S:
- break;
- case CLSTART_T:
- name = (const char *) obj;
- subunit_test_start (name);
- break;
- case CLEND_T:
- tr = (TestResult *) obj;
- {
- char *name = ck_strdup_printf ("%s:%s", tr->tcname, tr->tname);
- char *msg = tr_short_str (tr);
-
- switch (tr->rtype) {
- case CK_PASS:
- subunit_test_pass (name);
- break;
- case CK_FAILURE:
- subunit_test_fail (name, msg);
- break;
- case CK_ERROR:
- subunit_test_error (name, msg);
- break;
- case CK_TEST_RESULT_INVALID:
- default:
- eprintf ("Bad result type in subunit_lfun", __FILE__, __LINE__);
- free (name);
- free (msg);
- }
- }
- break;
- default:
- eprintf ("Bad event type received in subunit_lfun", __FILE__, __LINE__);
- }
-}
-#endif
-
-static FILE *
-srunner_open_file (const char *filename)
-{
- FILE *f = NULL;
-
- if (strcmp (filename, STDOUT_OVERRIDE_LOG_FILE_NAME) == 0) {
- f = stdout;
- } else {
- f = fopen (filename, "w");
- if (f == NULL) {
- eprintf ("Error in call to fopen while opening file %s:", __FILE__,
- __LINE__ - 2, filename);
- }
- }
- return f;
-}
-
-FILE *
-srunner_open_lfile (SRunner * sr)
-{
- FILE *f = NULL;
-
- if (srunner_has_log (sr)) {
- f = srunner_open_file (srunner_log_fname (sr));
- }
- return f;
-}
-
-FILE *
-srunner_open_xmlfile (SRunner * sr)
-{
- FILE *f = NULL;
-
- if (srunner_has_xml (sr)) {
- f = srunner_open_file (srunner_xml_fname (sr));
- }
- return f;
-}
-
-FILE *
-srunner_open_tapfile (SRunner * sr)
-{
- FILE *f = NULL;
-
- if (srunner_has_tap (sr)) {
- f = srunner_open_file (srunner_tap_fname (sr));
- }
- return f;
-}
-
-void
-srunner_init_logging (SRunner * sr, enum print_output print_mode)
-{
- FILE *f;
-
- sr->loglst = check_list_create ();
-#if ENABLE_SUBUNIT
- if (print_mode != CK_SUBUNIT)
-#endif
- srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode);
-#if ENABLE_SUBUNIT
- else
- srunner_register_lfun (sr, stdout, 0, subunit_lfun, print_mode);
-#endif
- f = srunner_open_lfile (sr);
- if (f) {
- srunner_register_lfun (sr, f, f != stdout, lfile_lfun, print_mode);
- }
- f = srunner_open_xmlfile (sr);
- if (f) {
- srunner_register_lfun (sr, f, f != stdout, xml_lfun, print_mode);
- }
- f = srunner_open_tapfile (sr);
- if (f) {
- srunner_register_lfun (sr, f, f != stdout, tap_lfun, print_mode);
- }
- srunner_send_evt (sr, NULL, CLINITLOG_SR);
-}
-
-void
-srunner_end_logging (SRunner * sr)
-{
- List *l;
- int rval;
-
- srunner_send_evt (sr, NULL, CLENDLOG_SR);
-
- l = sr->loglst;
- for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
- Log *lg = (Log *) check_list_val (l);
-
- if (lg->close) {
- rval = fclose (lg->lfile);
- if (rval != 0)
- eprintf ("Error in call to fclose while closing log file:",
- __FILE__, __LINE__ - 2);
- }
- free (lg);
- }
- check_list_free (l);
- sr->loglst = NULL;
-}
diff --git a/libs/gst/check/libcheck/check_log.h b/libs/gst/check/libcheck/check_log.h
deleted file mode 100644
index c1936f973f..0000000000
--- a/libs/gst/check/libcheck/check_log.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_LOG_H
-#define CHECK_LOG_H
-
-void log_srunner_start (SRunner * sr);
-void log_srunner_end (SRunner * sr);
-void log_suite_start (SRunner * sr, Suite * s);
-void log_suite_end (SRunner * sr, Suite * s);
-void log_test_end (SRunner * sr, TestResult * tr);
-void log_test_start (SRunner * sr, TCase * tc, TF * tfun);
-
-void stdout_lfun (SRunner * sr, FILE * file, enum print_output,
- void *obj, enum cl_event evt);
-
-void lfile_lfun (SRunner * sr, FILE * file, enum print_output,
- void *obj, enum cl_event evt);
-
-void xml_lfun (SRunner * sr, FILE * file, enum print_output,
- void *obj, enum cl_event evt);
-
-void tap_lfun (SRunner * sr, FILE * file, enum print_output,
- void *obj, enum cl_event evt);
-
-void subunit_lfun (SRunner * sr, FILE * file, enum print_output,
- void *obj, enum cl_event evt);
-
-void srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
- LFun lfun, enum print_output);
-
-FILE *srunner_open_lfile (SRunner * sr);
-FILE *srunner_open_xmlfile (SRunner * sr);
-FILE *srunner_open_tapfile (SRunner * sr);
-void srunner_init_logging (SRunner * sr, enum print_output print_mode);
-void srunner_end_logging (SRunner * sr);
-
-#endif /* CHECK_LOG_H */
diff --git a/libs/gst/check/libcheck/check_msg.c b/libs/gst/check/libcheck/check_msg.c
deleted file mode 100644
index e862c5c706..0000000000
--- a/libs/gst/check/libcheck/check_msg.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-#include "check_error.h"
-#include "internal-check.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_msg.h"
-#include "check_pack.h"
-#include "check_str.h"
-
-
-/* 'Pipe' is implemented as a temporary file to overcome message
- * volume limitations outlined in bug #482012. This scheme works well
- * with the existing usage wherein the parent does not begin reading
- * until the child has done writing and exited.
- *
- * Pipe life cycle:
- * - The parent creates a tmpfile().
- * - The fork() call has the effect of duplicating the file descriptor
- * and copying (on write) the FILE* data structures.
- * - The child writes to the file, and its dup'ed file descriptor and
- * data structures are cleaned up on child process exit.
- * - Before reading, the parent rewind()'s the file to reset both
- * FILE* and underlying file descriptor location data.
- * - When finished, the parent fclose()'s the FILE*, deleting the
- * temporary file, per tmpfile()'s semantics.
- *
- * This scheme may break down if the usage changes to asynchronous
- * reading and writing.
- */
-
-static FILE *send_file1;
-static char *send_file1_name;
-static FILE *send_file2;
-static char *send_file2_name;
-
-static FILE *get_pipe (void);
-static void setup_pipe (void);
-static void teardown_pipe (void);
-static TestResult *construct_test_result (RcvMsg * rmsg, int waserror);
-static void tr_set_loc_by_ctx (TestResult * tr, enum ck_result_ctx ctx,
- RcvMsg * rmsg);
-static FILE *
-get_pipe (void)
-{
- if (send_file2 != 0) {
- return send_file2;
- }
-
- if (send_file1 != 0) {
- return send_file1;
- }
-
- eprintf ("No messaging setup", __FILE__, __LINE__);
-
- return NULL;
-}
-
-void
-send_failure_info (const char *msg)
-{
- FailMsg fmsg;
-
- fmsg.msg = strdup (msg);
- ppack (get_pipe (), CK_MSG_FAIL, (CheckMsg *) & fmsg);
- free (fmsg.msg);
-}
-
-void
-send_duration_info (int duration)
-{
- DurationMsg dmsg;
-
- dmsg.duration = duration;
- ppack (get_pipe (), CK_MSG_DURATION, (CheckMsg *) & dmsg);
-}
-
-void
-send_loc_info (const char *file, int line)
-{
- LocMsg lmsg;
-
- lmsg.file = strdup (file);
- lmsg.line = line;
- ppack (get_pipe (), CK_MSG_LOC, (CheckMsg *) & lmsg);
- free (lmsg.file);
-}
-
-void
-send_ctx_info (enum ck_result_ctx ctx)
-{
- CtxMsg cmsg;
-
- cmsg.ctx = ctx;
- ppack (get_pipe (), CK_MSG_CTX, (CheckMsg *) & cmsg);
-}
-
-TestResult *
-receive_test_result (int waserror)
-{
- FILE *fp;
- RcvMsg *rmsg;
- TestResult *result;
-
- fp = get_pipe ();
- if (fp == NULL) {
- eprintf ("Error in call to get_pipe", __FILE__, __LINE__ - 2);
- }
-
- rewind (fp);
- rmsg = punpack (fp);
-
- if (rmsg == NULL) {
- eprintf ("Error in call to punpack", __FILE__, __LINE__ - 4);
- }
-
- teardown_pipe ();
- setup_pipe ();
-
- result = construct_test_result (rmsg, waserror);
- rcvmsg_free (rmsg);
- return result;
-}
-
-static void
-tr_set_loc_by_ctx (TestResult * tr, enum ck_result_ctx ctx, RcvMsg * rmsg)
-{
- if (ctx == CK_CTX_TEST) {
- tr->file = rmsg->test_file;
- tr->line = rmsg->test_line;
- rmsg->test_file = NULL;
- rmsg->test_line = -1;
- } else {
- tr->file = rmsg->fixture_file;
- tr->line = rmsg->fixture_line;
- rmsg->fixture_file = NULL;
- rmsg->fixture_line = -1;
- }
-}
-
-static TestResult *
-construct_test_result (RcvMsg * rmsg, int waserror)
-{
- TestResult *tr;
-
- if (rmsg == NULL)
- return NULL;
-
- tr = tr_create ();
-
- if (rmsg->msg != NULL || waserror) {
- if (rmsg->failctx != CK_CTX_INVALID) {
- tr->ctx = rmsg->failctx;
- } else {
- tr->ctx = rmsg->lastctx;
- }
-
- tr->msg = rmsg->msg;
- rmsg->msg = NULL;
- tr_set_loc_by_ctx (tr, tr->ctx, rmsg);
- } else if (rmsg->lastctx == CK_CTX_SETUP) {
- tr->ctx = CK_CTX_SETUP;
- tr->msg = NULL;
- tr_set_loc_by_ctx (tr, CK_CTX_SETUP, rmsg);
- } else {
- tr->ctx = CK_CTX_TEST;
- tr->msg = NULL;
- tr->duration = rmsg->duration;
- tr_set_loc_by_ctx (tr, CK_CTX_TEST, rmsg);
- }
-
- return tr;
-}
-
-void
-setup_messaging (void)
-{
- setup_pipe ();
-}
-
-void
-teardown_messaging (void)
-{
- teardown_pipe ();
-}
-
-/**
- * Open a temporary file.
- *
- * If the file could be unlinked upon creation, the name
- * of the file is not returned via 'name'. However, if the
- * file could not be unlinked, the name is returned,
- * expecting the caller to both delete the file and
- * free the 'name' field after the file is closed.
- */
-FILE *
-open_tmp_file (char **name)
-{
- FILE *file = NULL;
-
- *name = NULL;
-
-#if !HAVE_MKSTEMP
- /* Windows does not like tmpfile(). This is likely because tmpfile()
- * call unlink() on the file before returning it, to make sure the
- * file is deleted when it is closed. The unlink() call also fails
- * on Windows if the file is still open. */
- /* also note that mkstemp is apparently a C90 replacement for tmpfile */
- /* perhaps all we need to do on Windows is set TMPDIR to whatever is
- stored in TEMP for tmpfile to work */
- /* and finally, the "b" from "w+b" is ignored on OS X, not sure about WIN32 */
-
- file = tmpfile ();
- if (file == NULL) {
- char *tmp = getenv ("TEMP");
- char *tmp_file = tempnam (tmp, "check_");
-
- /*
- * Note, tempnam is not enough to get a unique name. Between
- * getting the name and opening the file, something else also
- * calling tempnam() could get the same name. It has been observed
- * on MinGW-w64 builds on Wine that this exact thing happens
- * if multiple instances of a unit tests are running concurrently.
- * To prevent two concurrent unit tests from getting the same file,
- * we append the pid to the file. The pid should be unique on the
- * system.
- */
- char *uniq_tmp_file = ck_strdup_printf ("%s.%d", tmp_file, getpid ());
-
- file = fopen (uniq_tmp_file, "w+b");
- *name = uniq_tmp_file;
- free (tmp_file);
- }
-#else
- int fd = -1;
- const char *tmp_dir = getenv ("TEMP");
- if (!tmp_dir) {
- tmp_dir = ".";
- }
-
- *name = ck_strdup_printf ("%s/check_XXXXXX", tmp_dir);
-
- if (-1 < (fd = mkstemp (*name))) {
- file = fdopen (fd, "w+b");
- if (0 == unlink (*name) || NULL == file) {
- free (*name);
- *name = NULL;
- }
- }
-#endif
- return file;
-}
-
-static void
-setup_pipe (void)
-{
- if (send_file1 == NULL) {
- send_file1 = open_tmp_file (&send_file1_name);
- return;
- }
- if (send_file2 == NULL) {
- send_file2 = open_tmp_file (&send_file2_name);
- return;
- }
- eprintf ("Only one nesting of suite runs supported", __FILE__, __LINE__);
-}
-
-static void
-teardown_pipe (void)
-{
- if (send_file2 != 0) {
- fclose (send_file2);
- send_file2 = 0;
- if (send_file2_name != NULL) {
- unlink (send_file2_name);
- free (send_file2_name);
- send_file2_name = NULL;
- }
- } else if (send_file1 != 0) {
- fclose (send_file1);
- send_file1 = 0;
- if (send_file1_name != NULL) {
- unlink (send_file1_name);
- free (send_file1_name);
- send_file1_name = NULL;
- }
- } else {
- eprintf ("No messaging setup", __FILE__, __LINE__);
- }
-}
diff --git a/libs/gst/check/libcheck/check_msg.h b/libs/gst/check/libcheck/check_msg.h
deleted file mode 100644
index b99a757f8e..0000000000
--- a/libs/gst/check/libcheck/check_msg.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_MSG_NEW_H
-#define CHECK_MSG_NEW_H
-
-
-/* Functions implementing messaging during test runs */
-
-void send_failure_info (const char *msg);
-void send_loc_info (const char *file, int line);
-void send_ctx_info (enum ck_result_ctx ctx);
-void send_duration_info (int duration);
-
-TestResult *receive_test_result (int waserror);
-
-void setup_messaging (void);
-void teardown_messaging (void);
-
-FILE *open_tmp_file (char **name);
-
-#endif /*CHECK_MSG_NEW_H */
diff --git a/libs/gst/check/libcheck/check_pack.c b/libs/gst/check/libcheck/check_pack.c
deleted file mode 100644
index 4925d88667..0000000000
--- a/libs/gst/check/libcheck/check_pack.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "internal-check.h"
-#include "check_error.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_pack.h"
-
-#ifndef HAVE_PTHREAD
-#define pthread_mutex_lock(arg)
-#define pthread_mutex_unlock(arg)
-#define pthread_cleanup_push(f,a) {
-#define pthread_cleanup_pop(e) }
-#endif
-
-/* Maximum size for one message in the message stream. */
-#define CK_MAX_MSG_SIZE 8192
-/* This is used to implement a sliding window on the receiving
- * side. When sending messages, we assure that no single message
- * is bigger than this (actually we check against CK_MAX_MSG_SIZE/2).
- * The usual size for a message is less than 80 bytes.
- * All this is done instead of the previous approach to allocate (actually
- * continuously reallocate) one big chunk for the whole message stream.
- * Problems were seen in the wild with up to 4 GB reallocations.
- */
-
-
-/* typedef an unsigned int that has at least 4 bytes */
-typedef uint32_t ck_uint32;
-
-
-static void pack_int (char **buf, int val);
-static int upack_int (char **buf);
-static void pack_str (char **buf, const char *str);
-static char *upack_str (char **buf);
-
-static int pack_ctx (char **buf, CtxMsg * cmsg);
-static int pack_loc (char **buf, LocMsg * lmsg);
-static int pack_fail (char **buf, FailMsg * fmsg);
-static int pack_duration (char **buf, DurationMsg * fmsg);
-static void upack_ctx (char **buf, CtxMsg * cmsg);
-static void upack_loc (char **buf, LocMsg * lmsg);
-static void upack_fail (char **buf, FailMsg * fmsg);
-static void upack_duration (char **buf, DurationMsg * fmsg);
-
-static void check_type (int type, const char *file, int line);
-static enum ck_msg_type upack_type (char **buf);
-static void pack_type (char **buf, enum ck_msg_type type);
-
-static int read_buf (FILE * fdes, int size, char *buf);
-static int get_result (char *buf, RcvMsg * rmsg);
-static void rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx);
-static void rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line);
-static RcvMsg *rcvmsg_create (void);
-void rcvmsg_free (RcvMsg * rmsg);
-
-typedef int (*pfun) (char **, CheckMsg *);
-typedef void (*upfun) (char **, CheckMsg *);
-
-static pfun pftab[] = {
- (pfun) pack_ctx,
- (pfun) pack_fail,
- (pfun) pack_loc,
- (pfun) pack_duration
-};
-
-static upfun upftab[] = {
- (upfun) upack_ctx,
- (upfun) upack_fail,
- (upfun) upack_loc,
- (upfun) upack_duration
-};
-
-int
-pack (enum ck_msg_type type, char **buf, CheckMsg * msg)
-{
- if (buf == NULL)
- return -1;
- if (msg == NULL)
- return 0;
-
- check_type (type, __FILE__, __LINE__);
-
- return pftab[type] (buf, msg);
-}
-
-int
-upack (char *buf, CheckMsg * msg, enum ck_msg_type *type)
-{
- char *obuf;
-
- if (buf == NULL)
- return -1;
-
- obuf = buf;
-
- *type = upack_type (&buf);
-
- check_type (*type, __FILE__, __LINE__);
-
- upftab[*type] (&buf, msg);
-
- return buf - obuf;
-}
-
-static void
-pack_int (char **buf, int val)
-{
- unsigned char *ubuf = (unsigned char *) *buf;
- ck_uint32 uval = val;
-
- ubuf[0] = (unsigned char) ((uval >> 24) & 0xFF);
- ubuf[1] = (unsigned char) ((uval >> 16) & 0xFF);
- ubuf[2] = (unsigned char) ((uval >> 8) & 0xFF);
- ubuf[3] = (unsigned char) (uval & 0xFF);
-
- *buf += 4;
-}
-
-static int
-upack_int (char **buf)
-{
- unsigned char *ubuf = (unsigned char *) *buf;
- ck_uint32 uval;
-
- uval =
- (ck_uint32) ((ubuf[0] << 24) | (ubuf[1] << 16) | (ubuf[2] << 8) |
- ubuf[3]);
-
- *buf += 4;
-
- return (int) uval;
-}
-
-static void
-pack_str (char **buf, const char *val)
-{
- int strsz;
-
- if (val == NULL)
- strsz = 0;
- else
- strsz = strlen (val);
-
- pack_int (buf, strsz);
-
- if (strsz > 0) {
- memcpy (*buf, val, strsz);
- *buf += strsz;
- }
-}
-
-static char *
-upack_str (char **buf)
-{
- char *val;
- int strsz;
-
- strsz = upack_int (buf);
-
- if (strsz > 0) {
- val = (char *) emalloc (strsz + 1);
- memcpy (val, *buf, strsz);
- val[strsz] = 0;
- *buf += strsz;
- } else {
- val = (char *) emalloc (1);
- *val = 0;
- }
-
- return val;
-}
-
-static void
-pack_type (char **buf, enum ck_msg_type type)
-{
- pack_int (buf, (int) type);
-}
-
-static enum ck_msg_type
-upack_type (char **buf)
-{
- return (enum ck_msg_type) upack_int (buf);
-}
-
-
-static int
-pack_ctx (char **buf, CtxMsg * cmsg)
-{
- char *ptr;
- int len;
-
- len = 4 + 4;
- *buf = ptr = (char *) emalloc (len);
-
- pack_type (&ptr, CK_MSG_CTX);
- pack_int (&ptr, (int) cmsg->ctx);
-
- return len;
-}
-
-static void
-upack_ctx (char **buf, CtxMsg * cmsg)
-{
- cmsg->ctx = (enum ck_result_ctx) upack_int (buf);
-}
-
-static int
-pack_duration (char **buf, DurationMsg * cmsg)
-{
- char *ptr;
- int len;
-
- len = 4 + 4;
- *buf = ptr = (char *) emalloc (len);
-
- pack_type (&ptr, CK_MSG_DURATION);
- pack_int (&ptr, cmsg->duration);
-
- return len;
-}
-
-static void
-upack_duration (char **buf, DurationMsg * cmsg)
-{
- cmsg->duration = upack_int (buf);
-}
-
-static int
-pack_loc (char **buf, LocMsg * lmsg)
-{
- char *ptr;
- int len;
-
- len = 4 + 4 + (lmsg->file ? strlen (lmsg->file) : 0) + 4;
- *buf = ptr = (char *) emalloc (len);
-
- pack_type (&ptr, CK_MSG_LOC);
- pack_str (&ptr, lmsg->file);
- pack_int (&ptr, lmsg->line);
-
- return len;
-}
-
-static void
-upack_loc (char **buf, LocMsg * lmsg)
-{
- lmsg->file = upack_str (buf);
- lmsg->line = upack_int (buf);
-}
-
-static int
-pack_fail (char **buf, FailMsg * fmsg)
-{
- char *ptr;
- int len;
-
- len = 4 + 4 + (fmsg->msg ? strlen (fmsg->msg) : 0);
- *buf = ptr = (char *) emalloc (len);
-
- pack_type (&ptr, CK_MSG_FAIL);
- pack_str (&ptr, fmsg->msg);
-
- return len;
-}
-
-static void
-upack_fail (char **buf, FailMsg * fmsg)
-{
- fmsg->msg = upack_str (buf);
-}
-
-static void
-check_type (int type, const char *file, int line)
-{
- if (type < 0 || type >= CK_MSG_LAST)
- eprintf ("Bad message type arg %d", file, line, type);
-}
-
-#ifdef HAVE_PTHREAD
-static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER;
-static void
-ppack_cleanup (void *mutex)
-{
- pthread_mutex_unlock ((pthread_mutex_t *) mutex);
-}
-#endif
-
-void
-ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
-{
- char *buf = NULL;
- int n;
- ssize_t r;
-
- n = pack (type, &buf, msg);
- /* Keep it on the safe side to not send too much data. */
- if (n > (CK_MAX_MSG_SIZE / 2))
- eprintf ("Message string too long", __FILE__, __LINE__ - 2);
-
- pthread_cleanup_push (ppack_cleanup, &ck_mutex_lock);
- pthread_mutex_lock (&ck_mutex_lock);
- r = fwrite (buf, 1, n, fdes);
- fflush (fdes);
- pthread_mutex_unlock (&ck_mutex_lock);
- pthread_cleanup_pop (0);
- if (r != n)
- eprintf ("Error in call to fwrite:", __FILE__, __LINE__ - 2);
-
- free (buf);
-}
-
-static int
-read_buf (FILE * fdes, int size, char *buf)
-{
- int n;
-
- n = fread (buf, 1, size, fdes);
-
- if (ferror (fdes)) {
- eprintf ("Error in call to fread:", __FILE__, __LINE__ - 4);
- }
-
- return n;
-}
-
-static int
-get_result (char *buf, RcvMsg * rmsg)
-{
- enum ck_msg_type type;
- CheckMsg msg;
- int n;
-
- n = upack (buf, &msg, &type);
- if (n == -1)
- eprintf ("Error in call to upack", __FILE__, __LINE__ - 2);
-
- if (type == CK_MSG_CTX) {
- CtxMsg *cmsg = (CtxMsg *) & msg;
-
- rcvmsg_update_ctx (rmsg, cmsg->ctx);
- } else if (type == CK_MSG_LOC) {
- LocMsg *lmsg = (LocMsg *) & msg;
-
- if (rmsg->failctx == CK_CTX_INVALID) {
- rcvmsg_update_loc (rmsg, lmsg->file, lmsg->line);
- }
- free (lmsg->file);
- } else if (type == CK_MSG_FAIL) {
- FailMsg *fmsg = (FailMsg *) & msg;
-
- if (rmsg->msg == NULL) {
- rmsg->msg = strdup (fmsg->msg);
- rmsg->failctx = rmsg->lastctx;
- } else {
- /* Skip subsequent failure messages, only happens for CK_NOFORK */
- }
- free (fmsg->msg);
- } else if (type == CK_MSG_DURATION) {
- DurationMsg *cmsg = (DurationMsg *) & msg;
-
- rmsg->duration = cmsg->duration;
- } else
- check_type (type, __FILE__, __LINE__);
-
- return n;
-}
-
-static void
-reset_rcv_test (RcvMsg * rmsg)
-{
- rmsg->test_line = -1;
- rmsg->test_file = NULL;
-}
-
-static void
-reset_rcv_fixture (RcvMsg * rmsg)
-{
- rmsg->fixture_line = -1;
- rmsg->fixture_file = NULL;
-}
-
-static RcvMsg *
-rcvmsg_create (void)
-{
- RcvMsg *rmsg;
-
- rmsg = (RcvMsg *) emalloc (sizeof (RcvMsg));
- rmsg->lastctx = CK_CTX_INVALID;
- rmsg->failctx = CK_CTX_INVALID;
- rmsg->msg = NULL;
- rmsg->duration = -1;
- reset_rcv_test (rmsg);
- reset_rcv_fixture (rmsg);
- return rmsg;
-}
-
-void
-rcvmsg_free (RcvMsg * rmsg)
-{
- free (rmsg->fixture_file);
- free (rmsg->test_file);
- free (rmsg->msg);
- free (rmsg);
-}
-
-static void
-rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx)
-{
- if (rmsg->lastctx != CK_CTX_INVALID) {
- free (rmsg->fixture_file);
- reset_rcv_fixture (rmsg);
- }
- rmsg->lastctx = ctx;
-}
-
-static void
-rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line)
-{
- if (rmsg->lastctx == CK_CTX_TEST) {
- free (rmsg->test_file);
- rmsg->test_line = line;
- rmsg->test_file = strdup (file);
- } else {
- free (rmsg->fixture_file);
- rmsg->fixture_line = line;
- rmsg->fixture_file = strdup (file);
- }
-}
-
-RcvMsg *
-punpack (FILE * fdes)
-{
- int nread, nparse, n;
- char *buf;
- RcvMsg *rmsg;
-
- rmsg = rcvmsg_create ();
-
- /* Allocate a buffer */
- buf = (char *) emalloc (CK_MAX_MSG_SIZE);
- /* Fill the buffer from the file */
- nread = read_buf (fdes, CK_MAX_MSG_SIZE, buf);
- nparse = nread;
- /* While not all parsed */
- while (nparse > 0) {
- /* Parse one message */
- n = get_result (buf, rmsg);
- nparse -= n;
- if (nparse < 0)
- eprintf ("Error in call to get_result", __FILE__, __LINE__ - 3);
- /* Move remaining data in buffer to the beginning */
- memmove (buf, buf + n, nparse);
- /* If EOF has not been seen */
- if (nread > 0) {
- /* Read more data into empty space at end of the buffer */
- nread = read_buf (fdes, n, buf + nparse);
- nparse += nread;
- }
- }
- free (buf);
-
- if (rmsg->lastctx == CK_CTX_INVALID) {
- free (rmsg);
- rmsg = NULL;
- }
-
- return rmsg;
-}
diff --git a/libs/gst/check/libcheck/check_pack.h b/libs/gst/check/libcheck/check_pack.h
deleted file mode 100644
index e73a196e64..0000000000
--- a/libs/gst/check/libcheck/check_pack.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_PACK_H
-#define CHECK_PACK_H
-
-
-enum ck_msg_type
-{
- CK_MSG_CTX,
- CK_MSG_FAIL,
- CK_MSG_LOC,
- CK_MSG_DURATION,
- CK_MSG_LAST
-};
-
-typedef struct CtxMsg
-{
- enum ck_result_ctx ctx;
-} CtxMsg;
-
-typedef struct LocMsg
-{
- int line;
- char *file;
-} LocMsg;
-
-typedef struct FailMsg
-{
- char *msg;
-} FailMsg;
-
-typedef struct DurationMsg
-{
- int duration;
-} DurationMsg;
-
-typedef union
-{
- CtxMsg ctx_msg;
- FailMsg fail_msg;
- LocMsg loc_msg;
- DurationMsg duration_msg;
-} CheckMsg;
-
-typedef struct RcvMsg
-{
- enum ck_result_ctx lastctx;
- enum ck_result_ctx failctx;
- char *fixture_file;
- int fixture_line;
- char *test_file;
- int test_line;
- char *msg;
- int duration;
-} RcvMsg;
-
-void rcvmsg_free (RcvMsg * rmsg);
-
-
-int pack (enum ck_msg_type type, char **buf, CheckMsg * msg);
-int upack (char *buf, CheckMsg * msg, enum ck_msg_type *type);
-
-void ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg);
-RcvMsg *punpack (FILE * fdes);
-
-#endif /*CHECK_PACK_H */
diff --git a/libs/gst/check/libcheck/check_print.c b/libs/gst/check/libcheck/check_print.c
deleted file mode 100644
index c94e47c80e..0000000000
--- a/libs/gst/check/libcheck/check_print.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "internal-check.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_str.h"
-#include "check_print.h"
-
-static void srunner_fprint_summary (FILE * file, SRunner * sr,
- enum print_output print_mode);
-static void srunner_fprint_results (FILE * file, SRunner * sr,
- enum print_output print_mode);
-
-
-void
-srunner_print (SRunner * sr, enum print_output print_mode)
-{
- srunner_fprint (stdout, sr, print_mode);
-}
-
-void
-srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode)
-{
- if (print_mode == CK_ENV) {
- print_mode = get_env_printmode ();
- }
-
- srunner_fprint_summary (file, sr, print_mode);
- srunner_fprint_results (file, sr, print_mode);
-}
-
-static void
-srunner_fprint_summary (FILE * file, SRunner * sr, enum print_output print_mode)
-{
-#if ENABLE_SUBUNIT
- if (print_mode == CK_SUBUNIT)
- return;
-#endif
-
- if (print_mode >= CK_MINIMAL) {
- char *str;
-
- str = sr_stat_str (sr);
- fprintf (file, "%s\n", str);
- free (str);
- }
- return;
-}
-
-static void
-srunner_fprint_results (FILE * file, SRunner * sr, enum print_output print_mode)
-{
- List *resultlst;
-
-#if ENABLE_SUBUNIT
- if (print_mode == CK_SUBUNIT)
- return;
-#endif
-
- resultlst = sr->resultlst;
-
- for (check_list_front (resultlst); !check_list_at_end (resultlst);
- check_list_advance (resultlst)) {
- TestResult *tr = (TestResult *) check_list_val (resultlst);
-
- tr_fprint (file, tr, print_mode);
- }
- return;
-}
-
-void
-fprint_xml_esc (FILE * file, const char *str)
-{
- /* The valid XML characters are as follows:
- * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
- * Characters that are outside of ASCII must be encoded. Further, the
- * following special characters:
- * " ' < > &
- * must be encoded. We assume that the incoming string may be a multibyte
- * character.
- */
-
- for (; *str != '\0'; str++) {
- char next = *str;
-
- /* handle special characters that must be escaped */
- if (next == '"' || next == '\'' || next == '<' || next == '>'
- || next == '&') {
- switch (next) {
- case '"':
- fputs ("&quot;", file);
- break;
- case '\'':
- fputs ("&apos;", file);
- break;
- case '<':
- fputs ("&lt;", file);
- break;
- case '>':
- fputs ("&gt;", file);
- break;
- case '&':
- fputs ("&amp;", file);
- break;
- }
- }
- /* printable ASCII */
- else if (next >= ' ' && next <= '~') {
- fputc (next, file);
- }
- /* Non-printable character */
- else if (next == 0x9 || next == 0xA || next == 0xD || next >= 0x20) {
- fprintf (file, "&#x%X;", next);
- }
- /* If it did not get printed, it is not a valid XML character */
- }
-}
-
-void
-tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode)
-{
- if (print_mode == CK_ENV) {
- print_mode = get_env_printmode ();
- }
-
- if ((print_mode >= CK_VERBOSE && tr->rtype == CK_PASS) ||
- (tr->rtype != CK_PASS && print_mode >= CK_NORMAL)) {
- char *trstr = tr_str (tr);
-
- fprintf (file, "%s\n", trstr);
- free (trstr);
- }
-}
-
-void
-tr_xmlprint (FILE * file, TestResult * tr,
- enum print_output print_mode CK_ATTRIBUTE_UNUSED)
-{
- char result[10];
- char *path_name = NULL;
- char *file_name = NULL;
- char *slash = NULL;
-
- switch (tr->rtype) {
- case CK_PASS:
- snprintf (result, sizeof (result), "%s", "success");
- break;
- case CK_FAILURE:
- snprintf (result, sizeof (result), "%s", "failure");
- break;
- case CK_ERROR:
- snprintf (result, sizeof (result), "%s", "error");
- break;
- case CK_TEST_RESULT_INVALID:
- default:
- abort ();
- break;
- }
-
- if (tr->file) {
- slash = strrchr (tr->file, '/');
- if (slash == NULL) {
- slash = strrchr (tr->file, '\\');
- }
-
- if (slash == NULL) {
- path_name = strdup (".");
- file_name = tr->file;
- } else {
- path_name = strdup (tr->file);
- path_name[slash - tr->file] = 0; /* Terminate the temporary string. */
- file_name = slash + 1;
- }
- }
-
-
- fprintf (file, " <test result=\"%s\">\n", result);
- fprintf (file, " <path>%s</path>\n",
- (path_name == NULL ? "" : path_name));
- fprintf (file, " <fn>%s:%d</fn>\n",
- (file_name == NULL ? "" : file_name), tr->line);
- fprintf (file, " <id>%s</id>\n", tr->tname);
- fprintf (file, " <iteration>%d</iteration>\n", tr->iter);
- fprintf (file, " <duration>%d.%06d</duration>\n",
- tr->duration < 0 ? -1 : tr->duration / US_PER_SEC,
- tr->duration < 0 ? 0 : tr->duration % US_PER_SEC);
- fprintf (file, " <description>");
- fprint_xml_esc (file, tr->tcname);
- fprintf (file, "</description>\n");
- fprintf (file, " <message>");
- fprint_xml_esc (file, tr->msg);
- fprintf (file, "</message>\n");
- fprintf (file, " </test>\n");
-
- free (path_name);
-}
-
-enum print_output
-get_env_printmode (void)
-{
- char *env = getenv ("CK_VERBOSITY");
-
- if (env == NULL)
- return CK_NORMAL;
- if (strcmp (env, "silent") == 0)
- return CK_SILENT;
- if (strcmp (env, "minimal") == 0)
- return CK_MINIMAL;
- if (strcmp (env, "verbose") == 0)
- return CK_VERBOSE;
- return CK_NORMAL;
-}
diff --git a/libs/gst/check/libcheck/check_print.h b/libs/gst/check/libcheck/check_print.h
deleted file mode 100644
index 20c0d221d4..0000000000
--- a/libs/gst/check/libcheck/check_print.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_PRINT_H
-#define CHECK_PRINT_H
-
-/* escape XML special characters (" ' < > &) in str and print to file */
-void fprint_xml_esc (FILE * file, const char *str);
-void tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode);
-void tr_xmlprint (FILE * file, TestResult * tr, enum print_output print_mode);
-void srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode);
-enum print_output get_env_printmode (void);
-
-
-#endif /* CHECK_PRINT_H */
diff --git a/libs/gst/check/libcheck/check_run.c b/libs/gst/check/libcheck/check_run.c
deleted file mode 100644
index a97379c91a..0000000000
--- a/libs/gst/check/libcheck/check_run.c
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <sys/types.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <setjmp.h>
-
-#include <glib.h>
-
-#include "internal-check.h"
-#include "check_error.h"
-#include "check_list.h"
-#include "check_impl.h"
-#include "check_msg.h"
-#include "check_log.h"
-
-enum rinfo
-{
- CK_R_SIG,
- CK_R_PASS,
- CK_R_EXIT,
- CK_R_FAIL_TEST,
- CK_R_FAIL_FIXTURE
-};
-
-enum tf_type
-{
- CK_FORK_TEST,
- CK_NOFORK_TEST,
- CK_NOFORK_FIXTURE
-};
-
-
-/* all functions are defined in the same order they are declared.
- functions that depend on forking are gathered all together.
- non-static functions are at the end of the file. */
-static void srunner_run_init (SRunner * sr, enum print_output print_mode);
-static void srunner_run_end (SRunner * sr, enum print_output print_mode);
-static void srunner_iterate_suites (SRunner * sr,
- const char *sname, const char *tcname,
- const char *include_tags,
- const char *exclude_tags, enum print_output print_mode);
-static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc);
-static void srunner_add_failure (SRunner * sr, TestResult * tf);
-static TestResult *srunner_run_setup (List * func_list,
- enum fork_status fork_usage, const char *test_name, const char *setup_name);
-static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
-static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc);
-static void srunner_run_teardown (List * fixture_list,
- enum fork_status fork_usage);
-static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc);
-static void tcase_run_checked_teardown (TCase * tc);
-static void srunner_run_tcase (SRunner * sr, TCase * tc);
-static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf,
- int i);
-static TestResult *receive_result_info_nofork (const char *tcname,
- const char *tname, int iter, int duration);
-static void set_nofork_info (TestResult * tr);
-static char *pass_msg (void);
-
-#if defined(HAVE_FORK) && HAVE_FORK==1
-static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf,
- int i);
-static TestResult *receive_result_info_fork (const char *tcname,
- const char *tname, int iter,
- int status, int expected_signal, signed char allowed_exit_value);
-static void set_fork_info (TestResult * tr, int status, int expected_signal,
- signed char allowed_exit_value);
-static char *signal_msg (int sig);
-static char *signal_error_msg (int signal_received, int signal_expected);
-static char *exit_msg (int exitstatus);
-static int waserror (int status, int expected_signal);
-
-static int alarm_received;
-static pid_t group_pid;
-static struct sigaction sigint_old_action;
-static struct sigaction sigterm_old_action;
-
-static void CK_ATTRIBUTE_UNUSED
-sig_handler (int sig_nr)
-{
- switch (sig_nr) {
- case SIGALRM:
- alarm_received = 1;
- killpg (group_pid, SIGKILL);
- break;
- case SIGTERM:
- case SIGINT:
- {
- pid_t own_group_pid;
- int child_sig = SIGTERM;
-
- if (sig_nr == SIGINT) {
- child_sig = SIGKILL;
- sigaction (SIGINT, &sigint_old_action, NULL);
- } else {
- sigaction (SIGTERM, &sigterm_old_action, NULL);
- }
-
- killpg (group_pid, child_sig);
-
- /* POSIX says that calling killpg(0)
- * does not necessarily mean to call it on the callers
- * group pid! */
- own_group_pid = getpgrp ();
- killpg (own_group_pid, sig_nr);
- break;
- }
- default:
- eprintf ("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
- break;
- }
-}
-#endif /* HAVE_FORK */
-
-#define MSG_LEN 100
-
-static void
-srunner_run_init (SRunner * sr, enum print_output print_mode)
-{
- set_fork_status (srunner_fork_status (sr));
- setup_messaging ();
- srunner_init_logging (sr, print_mode);
- log_srunner_start (sr);
-}
-
-static void
-srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
-{
- log_srunner_end (sr);
- srunner_end_logging (sr);
- teardown_messaging ();
- set_fork_status (CK_FORK);
-}
-
-static void
-srunner_iterate_suites (SRunner * sr,
- const char *sname, const char *tcname,
- const char *include_tags,
- const char *exclude_tags, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
-{
- List *include_tag_lst;
- List *exclude_tag_lst;
- List *slst;
- List *tcl;
- TCase *tc;
-
- slst = sr->slst;
-
- include_tag_lst = tag_string_to_list (include_tags);
- exclude_tag_lst = tag_string_to_list (exclude_tags);
-
- for (check_list_front (slst); !check_list_at_end (slst);
- check_list_advance (slst)) {
- Suite *s = (Suite *) check_list_val (slst);
-
- if (((sname != NULL) && (strcmp (sname, s->name) != 0))
- || ((tcname != NULL) && (!suite_tcase (s, tcname))))
- continue;
-
- log_suite_start (sr, s);
-
- tcl = s->tclst;
-
- for (check_list_front (tcl); !check_list_at_end (tcl);
- check_list_advance (tcl)) {
- tc = (TCase *) check_list_val (tcl);
-
- if ((tcname != NULL) && (strcmp (tcname, tc->name) != 0)) {
- continue;
- }
- if (include_tags != NULL) {
- if (!tcase_matching_tag (tc, include_tag_lst)) {
- continue;
- }
- }
- if (exclude_tags != NULL) {
- if (tcase_matching_tag (tc, exclude_tag_lst)) {
- continue;
- }
- }
-
- srunner_run_tcase (sr, tc);
- }
-
- log_suite_end (sr, s);
- }
-
- check_list_apply (include_tag_lst, free);
- check_list_apply (exclude_tag_lst, free);
- check_list_free (include_tag_lst);
- check_list_free (exclude_tag_lst);
-}
-
-static void
-srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
-{
- List *tfl;
- TF *tfun;
- TestResult *tr = NULL;
-
- tfl = tc->tflst;
-
- for (check_list_front (tfl); !check_list_at_end (tfl);
- check_list_advance (tfl)) {
- int i;
-
- tfun = (TF *) check_list_val (tfl);
-
- for (i = tfun->loop_start; i < tfun->loop_end; i++) {
- log_test_start (sr, tc, tfun);
- switch (srunner_fork_status (sr)) {
- case CK_FORK:
-#if defined(HAVE_FORK) && HAVE_FORK==1
- tr = tcase_run_tfun_fork (sr, tc, tfun, i);
-#else /* HAVE_FORK */
- eprintf ("This version does not support fork", __FILE__, __LINE__);
-#endif /* HAVE_FORK */
- break;
- case CK_NOFORK:
- tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
- break;
- case CK_FORK_GETENV:
- default:
- eprintf ("Bad fork status in SRunner", __FILE__, __LINE__);
- }
-
- if (NULL != tr) {
- srunner_add_failure (sr, tr);
- log_test_end (sr, tr);
- }
- }
- }
-}
-
-static void
-srunner_add_failure (SRunner * sr, TestResult * tr)
-{
- check_list_add_end (sr->resultlst, tr);
- sr->stats->n_checked++; /* count checks during setup, test, and teardown */
- if (tr->rtype == CK_FAILURE)
- sr->stats->n_failed++;
- else if (tr->rtype == CK_ERROR)
- sr->stats->n_errors++;
-
-}
-
-static TestResult *
-srunner_run_setup (List * fixture_list, enum fork_status fork_usage,
- const char *test_name, const char *setup_name)
-{
- TestResult *tr = NULL;
- Fixture *setup_fixture;
-
- if (fork_usage == CK_FORK) {
- send_ctx_info (CK_CTX_SETUP);
- }
-
- for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
- check_list_advance (fixture_list)) {
- setup_fixture = (Fixture *) check_list_val (fixture_list);
-
- if (fork_usage == CK_NOFORK) {
- send_ctx_info (CK_CTX_SETUP);
-
- if (0 == setjmp (error_jmp_buffer)) {
- setup_fixture->fun ();
- }
-
- /* Stop the setup and return the failure in nofork mode. */
- tr = receive_result_info_nofork (test_name, setup_name, 0, -1);
- if (tr->rtype != CK_PASS) {
- break;
- }
-
- free (tr->file);
- free (tr->msg);
- free (tr);
- tr = NULL;
- } else {
- setup_fixture->fun ();
- }
- }
-
- return tr;
-}
-
-static int
-srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
-{
- TestResult *tr = NULL;
- int rval = 1;
-
- set_fork_status (CK_NOFORK);
- tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name,
- "unchecked_setup");
- set_fork_status (srunner_fork_status (sr));
-
- if (tr != NULL && tr->rtype != CK_PASS) {
- srunner_add_failure (sr, tr);
- rval = 0;
- }
-
- return rval;
-}
-
-static TestResult *
-tcase_run_checked_setup (SRunner * sr, TCase * tc)
-{
- TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr),
- tc->name, "checked_setup");
-
- return tr;
-}
-
-static void
-srunner_run_teardown (List * fixture_list, enum fork_status fork_usage)
-{
- Fixture *fixture;
-
- for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
- check_list_advance (fixture_list)) {
- fixture = (Fixture *) check_list_val (fixture_list);
- send_ctx_info (CK_CTX_TEARDOWN);
-
- if (fork_usage == CK_NOFORK) {
- if (0 == setjmp (error_jmp_buffer)) {
- fixture->fun ();
- } else {
- /* Abort the remaining teardowns */
- break;
- }
- } else {
- fixture->fun ();
- }
- }
-}
-
-static void
-srunner_run_unchecked_teardown (SRunner * sr, TCase * tc)
-{
- srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr));
-}
-
-static void
-tcase_run_checked_teardown (TCase * tc)
-{
- srunner_run_teardown (tc->ch_tflst, CK_NOFORK);
-}
-
-static void
-srunner_run_tcase (SRunner * sr, TCase * tc)
-{
- if (srunner_run_unchecked_setup (sr, tc)) {
- srunner_iterate_tcase_tfuns (sr, tc);
- srunner_run_unchecked_teardown (sr, tc);
- }
-}
-
-static TestResult *
-tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
-{
- TestResult *tr;
- struct timespec ts_start = { 0, 0 }, ts_end = {
- 0, 0};
-
- tr = tcase_run_checked_setup (sr, tc);
- if (tr == NULL) {
- clock_gettime (check_get_clockid (), &ts_start);
- if (0 == setjmp (error_jmp_buffer)) {
- tfun->fn (i);
- }
- clock_gettime (check_get_clockid (), &ts_end);
- tcase_run_checked_teardown (tc);
- return receive_result_info_nofork (tc->name, tfun->name, i,
- DIFF_IN_USEC (ts_start, ts_end));
- }
-
- return tr;
-}
-
-static TestResult *
-receive_result_info_nofork (const char *tcname,
- const char *tname, int iter, int duration)
-{
- TestResult *tr;
-
- tr = receive_test_result (0);
- if (tr == NULL) {
- eprintf ("Failed to receive test result", __FILE__, __LINE__);
- } else {
- tr->tcname = tcname;
- tr->tname = tname;
- tr->iter = iter;
- tr->duration = duration;
- set_nofork_info (tr);
- }
-
- return tr;
-}
-
-static void
-set_nofork_info (TestResult * tr)
-{
- if (tr->msg == NULL) {
- tr->rtype = CK_PASS;
- tr->msg = pass_msg ();
- } else {
- tr->rtype = CK_FAILURE;
- }
-}
-
-static char *
-pass_msg (void)
-{
- return strdup ("Passed");
-}
-
-#if defined(HAVE_FORK) && HAVE_FORK==1
-static TestResult *
-tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
-{
- pid_t pid_w;
- pid_t pid;
- int status = 0;
- struct timespec ts_start = { 0, 0 }, ts_end = {
- 0, 0};
-
- timer_t timerid;
- struct itimerspec timer_spec;
- TestResult *tr;
-
-
- pid = fork ();
- if (pid == -1)
- eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
- if (pid == 0) {
- setpgid (0, 0);
- group_pid = getpgrp ();
- tr = tcase_run_checked_setup (sr, tc);
- free (tr);
- clock_gettime (check_get_clockid (), &ts_start);
- tfun->fn (i);
- clock_gettime (check_get_clockid (), &ts_end);
- tcase_run_checked_teardown (tc);
- send_duration_info (DIFF_IN_USEC (ts_start, ts_end));
- g_thread_pool_stop_unused_threads ();
- exit (EXIT_SUCCESS);
- } else {
- group_pid = pid;
- }
-
- alarm_received = 0;
-
- if (timer_create (check_get_clockid (),
- NULL /* fire SIGALRM if timer expires */ ,
- &timerid) == 0) {
- /* Set the timer to fire once */
- timer_spec.it_value = tc->timeout;
- timer_spec.it_interval.tv_sec = 0;
- timer_spec.it_interval.tv_nsec = 0;
- if (timer_settime (timerid, 0, &timer_spec, NULL) == 0) {
- do {
- pid_w = waitpid (pid, &status, 0);
- }
- while (pid_w == -1);
- } else {
- eprintf ("Error in call to timer_settime:", __FILE__, __LINE__);
- }
-
- /* If the timer has not fired, disable it */
- timer_delete (timerid);
- } else {
- eprintf ("Error in call to timer_create:", __FILE__, __LINE__);
- }
-
- killpg (pid, SIGKILL); /* Kill remaining processes. */
-
- return receive_result_info_fork (tc->name, tfun->name, i, status,
- tfun->signal, tfun->allowed_exit_value);
-}
-
-static TestResult *
-receive_result_info_fork (const char *tcname,
- const char *tname,
- int iter, int status, int expected_signal, signed char allowed_exit_value)
-{
- TestResult *tr;
-
- tr = receive_test_result (waserror (status, expected_signal));
- if (tr == NULL) {
- eprintf ("Failed to receive test result", __FILE__, __LINE__);
- } else {
- tr->tcname = tcname;
- tr->tname = tname;
- tr->iter = iter;
- set_fork_info (tr, status, expected_signal, allowed_exit_value);
- }
-
- return tr;
-}
-
-static void
-set_fork_info (TestResult * tr, int status, int signal_expected,
- signed char allowed_exit_value)
-{
- int was_sig = WIFSIGNALED (status);
- int was_exit = WIFEXITED (status);
- signed char exit_status = WEXITSTATUS (status);
- int signal_received = WTERMSIG (status);
-
- if (was_sig) {
- if (signal_expected == signal_received) {
- if (alarm_received) {
- /* Got alarm instead of signal */
- tr->rtype = CK_ERROR;
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = signal_error_msg (signal_received, signal_expected);
- } else {
- tr->rtype = CK_PASS;
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = pass_msg ();
- }
- } else if (signal_expected != 0) {
- /* signal received, but not the expected one */
- tr->rtype = CK_ERROR;
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = signal_error_msg (signal_received, signal_expected);
- } else {
- /* signal received and none expected */
- tr->rtype = CK_ERROR;
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = signal_msg (signal_received);
- }
- } else if (signal_expected == 0) {
- if (was_exit && exit_status == allowed_exit_value) {
- tr->rtype = CK_PASS;
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = pass_msg ();
- } else if (was_exit && exit_status != allowed_exit_value) {
- if (tr->msg == NULL) { /* early exit */
- tr->rtype = CK_ERROR;
- tr->msg = exit_msg (exit_status);
- } else {
- tr->rtype = CK_FAILURE;
- }
- }
- } else { /* a signal was expected and none raised */
- if (was_exit) {
- if (tr->msg != NULL) {
- free (tr->msg);
- }
- tr->msg = exit_msg (exit_status);
- tr->rtype = CK_FAILURE; /* normal exit status */
- }
- }
-}
-
-static char *
-signal_msg (int signal)
-{
- char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
-
- if (alarm_received) {
- snprintf (msg, MSG_LEN, "Test timeout expired");
- } else {
- snprintf (msg, MSG_LEN, "Received signal %d (%s)",
- signal, strsignal (signal));
- }
- return msg;
-}
-
-static char *
-signal_error_msg (int signal_received, int signal_expected)
-{
- char *sig_r_str;
- char *sig_e_str;
- char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
-
- sig_r_str = strdup (strsignal (signal_received));
- sig_e_str = strdup (strsignal (signal_expected));
- if (alarm_received) {
- snprintf (msg, MSG_LEN,
- "Test timeout expired, expected signal %d (%s)",
- signal_expected, sig_e_str);
- } else {
- snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
- signal_received, sig_r_str, signal_expected, sig_e_str);
- }
- free (sig_r_str);
- free (sig_e_str);
- return msg;
-}
-
-static char *
-exit_msg (int exitval)
-{
- char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
-
- snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval);
- return msg;
-}
-
-static int
-waserror (int status, int signal_expected)
-{
- int was_sig = WIFSIGNALED (status);
- int was_exit = WIFEXITED (status);
- int exit_status = WEXITSTATUS (status);
- int signal_received = WTERMSIG (status);
-
- return ((was_sig && (signal_received != signal_expected)) ||
- (was_exit && exit_status != 0));
-}
-#endif /* HAVE_FORK */
-
-enum fork_status
-srunner_fork_status (SRunner * sr)
-{
- if (sr->fstat == CK_FORK_GETENV) {
- char *env = getenv ("CK_FORK");
-
- if (env == NULL)
-#if defined(HAVE_FORK) && HAVE_FORK==1
- return CK_FORK;
-#else
- return CK_NOFORK;
-#endif
- if (strcmp (env, "no") == 0)
- return CK_NOFORK;
- else {
-#if defined(HAVE_FORK) && HAVE_FORK==1
- return CK_FORK;
-#else /* HAVE_FORK */
- eprintf ("This version does not support fork", __FILE__, __LINE__);
- /* Ignoring, as Check is not compiled with fork support. */
- return CK_NOFORK;
-#endif /* HAVE_FORK */
- }
- } else
- return sr->fstat;
-}
-
-void
-srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
-{
-#if !defined(HAVE_FORK) || HAVE_FORK==0
- /* If fork() is unavailable, do not allow a fork mode to be set */
- if (fstat != CK_NOFORK) {
- eprintf ("This version does not support fork", __FILE__, __LINE__);
- /* Overriding, as Check is not compiled with fork support. */
- fstat = CK_NOFORK;
- }
-#endif /* ! HAVE_FORK */
- sr->fstat = fstat;
-}
-
-void
-srunner_run_all (SRunner * sr, enum print_output print_mode)
-{
- srunner_run (sr, NULL, /* All test suites. */
- NULL, /* All test cases. */
- print_mode);
-}
-
-void
-srunner_run_tagged (SRunner * sr, const char *sname, const char *tcname,
- const char *include_tags, const char *exclude_tags,
- enum print_output print_mode)
-{
-#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
- static struct sigaction sigalarm_old_action;
- static struct sigaction sigalarm_new_action;
- static struct sigaction sigint_new_action;
- static struct sigaction sigterm_new_action;
-#endif /* HAVE_SIGACTION && HAVE_FORK */
-
- /* Get the selected test suite and test case from the
- environment. */
- if (!tcname)
- tcname = getenv ("CK_RUN_CASE");
- if (!sname)
- sname = getenv ("CK_RUN_SUITE");
- if (!include_tags)
- include_tags = getenv ("CK_INCLUDE_TAGS");
- if (!exclude_tags)
- exclude_tags = getenv ("CK_EXCLUDE_TAGS");
-
- if (sr == NULL)
- return;
- if (print_mode >= CK_LAST) {
- eprintf ("Bad print_mode argument to srunner_run_all: %d",
- __FILE__, __LINE__, print_mode);
- }
-#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
- memset (&sigalarm_new_action, 0, sizeof (sigalarm_new_action));
- sigalarm_new_action.sa_handler = sig_handler;
- sigaction (SIGALRM, &sigalarm_new_action, &sigalarm_old_action);
-
- memset (&sigint_new_action, 0, sizeof (sigint_new_action));
- sigint_new_action.sa_handler = sig_handler;
- sigaction (SIGINT, &sigint_new_action, &sigint_old_action);
-
- memset (&sigterm_new_action, 0, sizeof (sigterm_new_action));
- sigterm_new_action.sa_handler = sig_handler;
- sigaction (SIGTERM, &sigterm_new_action, &sigterm_old_action);
-#endif /* HAVE_SIGACTION && HAVE_FORK */
- srunner_run_init (sr, print_mode);
- srunner_iterate_suites (sr, sname, tcname, include_tags, exclude_tags,
- print_mode);
- srunner_run_end (sr, print_mode);
-#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
- sigaction (SIGALRM, &sigalarm_old_action, NULL);
- sigaction (SIGINT, &sigint_old_action, NULL);
- sigaction (SIGTERM, &sigterm_old_action, NULL);
-#endif /* HAVE_SIGACTION && HAVE_FORK */
-}
-
-void
-srunner_run (SRunner * sr, const char *sname, const char *tcname,
- enum print_output print_mode)
-{
- srunner_run_tagged (sr, sname, tcname, NULL, NULL, print_mode);
-}
-
-pid_t
-check_fork (void)
-{
-#if defined(HAVE_FORK) && HAVE_FORK==1
- pid_t pid = fork ();
-
- /* Set the process to a process group to be able to kill it easily. */
- if (pid >= 0) {
- setpgid (pid, group_pid);
- }
- return pid;
-#else /* HAVE_FORK */
- eprintf ("This version does not support fork", __FILE__, __LINE__);
- return 0;
-#endif /* HAVE_FORK */
-}
-
-void
-check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
-{
-#if defined(HAVE_FORK) && HAVE_FORK==1
- pid_t pid_w;
- int status;
-
- if (pid > 0) {
- do {
- pid_w = waitpid (pid, &status, 0);
- }
- while (pid_w == -1);
- if (waserror (status, 0)) {
- g_thread_pool_stop_unused_threads ();
- exit (EXIT_FAILURE);
- }
- }
- g_thread_pool_stop_unused_threads ();
- exit (EXIT_SUCCESS);
-#else /* HAVE_FORK */
- eprintf ("This version does not support fork", __FILE__, __LINE__);
- /* Ignoring, as Check is not compiled with fork support. */
- exit (EXIT_FAILURE);
-#endif /* HAVE_FORK */
-}
diff --git a/libs/gst/check/libcheck/check_str.c b/libs/gst/check/libcheck/check_str.c
deleted file mode 100644
index b2e64071b5..0000000000
--- a/libs/gst/check/libcheck/check_str.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat/libcompat.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "internal-check.h"
-#include "check_list.h"
-#include "check_error.h"
-#include "check_impl.h"
-#include "check_str.h"
-
-static const char *tr_type_str (TestResult * tr);
-static int percent_passed (TestStats * t);
-
-char *
-tr_str (TestResult * tr)
-{
- const char *exact_msg;
- char *rstr;
-
- exact_msg = (tr->rtype == CK_ERROR) ? "(after this point) " : "";
-
- rstr = ck_strdup_printf ("%s:%d:%s:%s:%s:%d: %s%s",
- tr->file, tr->line,
- tr_type_str (tr), tr->tcname, tr->tname, tr->iter, exact_msg, tr->msg);
-
- return rstr;
-}
-
-char *
-tr_short_str (TestResult * tr)
-{
- const char *exact_msg;
- char *rstr;
-
- exact_msg = (tr->rtype == CK_ERROR) ? "(after this point) " : "";
-
- rstr = ck_strdup_printf ("%s:%d: %s%s",
- tr->file, tr->line, exact_msg, tr->msg);
-
- return rstr;
-}
-
-char *
-sr_stat_str (SRunner * sr)
-{
- char *str;
- TestStats *ts;
-
- ts = sr->stats;
-
- str = ck_strdup_printf ("%d%%: Checks: %d, Failures: %d, Errors: %d",
- percent_passed (ts), ts->n_checked, ts->n_failed, ts->n_errors);
-
- return str;
-}
-
-char *
-ck_strdup_printf (const char *fmt, ...)
-{
- /* Guess we need no more than 100 bytes. */
- int n;
- size_t size = 100;
- char *p;
- va_list ap;
-
- p = (char *) emalloc (size);
-
- while (1) {
- /* Try to print in the allocated space. */
- va_start (ap, fmt);
- n = vsnprintf (p, size, fmt, ap);
- va_end (ap);
- /* If that worked, return the string. */
- if (n > -1 && n < (int) size)
- return p;
-
- /* Else try again with more space. */
- if (n > -1) /* C99 conform vsnprintf() */
- size = (size_t) n + 1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
-
- p = (char *) erealloc (p, size);
- }
-}
-
-static const char *
-tr_type_str (TestResult * tr)
-{
- const char *str = NULL;
-
- if (tr->ctx == CK_CTX_TEST) {
- if (tr->rtype == CK_PASS)
- str = "P";
- else if (tr->rtype == CK_FAILURE)
- str = "F";
- else if (tr->rtype == CK_ERROR)
- str = "E";
- } else
- str = "S";
-
- return str;
-}
-
-static int
-percent_passed (TestStats * t)
-{
- if (t->n_failed == 0 && t->n_errors == 0)
- return 100;
- else if (t->n_checked == 0)
- return 0;
- else
- return (int) ((float) (t->n_checked - (t->n_failed + t->n_errors)) /
- (float) t->n_checked * 100);
-}
diff --git a/libs/gst/check/libcheck/check_str.h b/libs/gst/check/libcheck/check_str.h
deleted file mode 100644
index f7fdba7107..0000000000
--- a/libs/gst/check/libcheck/check_str.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef CHECK_STR_H
-#define CHECK_STR_H
-
-/* Return a string representation of the given TestResult. Return
- value has been malloc'd, and must be freed by the caller */
-char *tr_str (TestResult * tr);
-
-/* Return a string representation of the given TestResult message
- without the test id or result type. This is suitable for separate
- formatting of the test and the message. Return value has been
- malloc'd, and must be freed by the caller */
-char *tr_short_str (TestResult * tr);
-
-/* Return a string representation of the given SRunner's run
- statistics (% passed, num run, passed, errors, failures). Return
- value has been malloc'd, and must be freed by the caller
-*/
-char *sr_stat_str (SRunner * sr);
-
-char *ck_strdup_printf (const char *fmt, ...);
-
-#endif /* CHECK_STR_H */
diff --git a/libs/gst/check/libcheck/libcompat/alarm.c b/libs/gst/check/libcheck/libcompat/alarm.c
deleted file mode 100644
index a973f2219c..0000000000
--- a/libs/gst/check/libcheck/libcompat/alarm.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-unsigned int
-alarm (unsigned int seconds CK_ATTRIBUTE_UNUSED)
-{
- assert (0);
- return 0;
-}
diff --git a/libs/gst/check/libcheck/libcompat/clock_gettime.c b/libs/gst/check/libcheck/libcompat/clock_gettime.c
deleted file mode 100644
index 51cfd8f9bf..0000000000
--- a/libs/gst/check/libcheck/libcompat/clock_gettime.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-#ifdef __APPLE__
-#include <mach/clock.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#include <TargetConditionals.h>
-/* CoreServices.h is only available on macOS */
-# if TARGET_OS_MAC && !TARGET_OS_IPHONE
-# include <CoreServices/CoreServices.h>
-# endif
-#include <unistd.h>
-#endif
-
-#define NANOSECONDS_PER_SECOND 1000000000
-
-
-
-int
-clock_gettime (clockid_t clk_id CK_ATTRIBUTE_UNUSED, struct timespec *ts)
-{
-
-#ifdef __APPLE__
- /* OS X does not have clock_gettime, use mach_absolute_time */
-
- static mach_timebase_info_data_t sTimebaseInfo;
- uint64_t rawTime;
- uint64_t nanos;
-
- rawTime = mach_absolute_time ();
-
- /*
- * OS X has a function to convert abs time to nano seconds: AbsoluteToNanoseconds
- * However, the function may not be available as we may not have
- * access to CoreServices. Because of this, we convert the abs time
- * to nano seconds manually.
- */
-
- /*
- * First grab the time base used on the system, if this is the first
- * time we are being called. We can check if the value is uninitialized,
- * as the denominator will be zero.
- */
- if (sTimebaseInfo.denom == 0) {
- (void) mach_timebase_info (&sTimebaseInfo);
- }
-
- /*
- * Do the conversion. We hope that the multiplication doesn't
- * overflow; the price you pay for working in fixed point.
- */
- nanos = rawTime * sTimebaseInfo.numer / sTimebaseInfo.denom;
-
- /*
- * Fill in the timespec container
- */
- ts->tv_sec = nanos / NANOSECONDS_PER_SECOND;
- ts->tv_nsec = nanos - (ts->tv_sec * NANOSECONDS_PER_SECOND);
-#else
- /*
- * As there is no function to fall back onto to get the current
- * time, zero out the time so the caller will have a sane value.
- */
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
-#endif
-
- return 0;
-}
diff --git a/libs/gst/check/libcheck/libcompat/getline.c b/libs/gst/check/libcheck/libcompat/getline.c
deleted file mode 100644
index edc073f1bd..0000000000
--- a/libs/gst/check/libcheck/libcompat/getline.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-#include <stdio.h>
-
-#define INITIAL_SIZE 16
-#define DELIMITER '\n'
-
-ssize_t
-getline (char **lineptr, size_t * n, FILE * stream)
-{
- ssize_t written = 0;
- int character;
-
- if (*lineptr == NULL || *n < INITIAL_SIZE) {
- free (*lineptr);
- *lineptr = (char *) malloc (INITIAL_SIZE);
- *n = INITIAL_SIZE;
- }
-
- while ((character = fgetc (stream)) != EOF) {
- written += 1;
- if (written >= *n) {
- *n = *n * 2;
- *lineptr = realloc (*lineptr, *n);
- }
-
- (*lineptr)[written - 1] = character;
-
- if (character == DELIMITER) {
- break;
- }
- }
-
- (*lineptr)[written] = '\0';
-
- return written;
-}
diff --git a/libs/gst/check/libcheck/libcompat/gettimeofday.c b/libs/gst/check/libcheck/libcompat/gettimeofday.c
deleted file mode 100644
index 78b327e6df..0000000000
--- a/libs/gst/check/libcheck/libcompat/gettimeofday.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-#include <errno.h>
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define EPOCHFILETIME (116444736000000000i64)
-#else
-#define EPOCHFILETIME (116444736000000000LL)
-#endif
-
-int
-gettimeofday (struct timeval *tv, void *tz)
-{
-#if _MSC_VER
- union
- {
- __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
- FILETIME ft;
- } now;
-
- GetSystemTimeAsFileTime (&now.ft);
- tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
- tv->tv_sec = (long) ((now.ns100 - EPOCHFILETIME) / 10000000LL);
- return (0);
-#else
- // Return that there is no implementation of this on the system
- errno = ENOSYS;
- return -1;
-#endif /* _MSC_VER */
-}
diff --git a/libs/gst/check/libcheck/libcompat/libcompat.c b/libs/gst/check/libcheck/libcompat/libcompat.c
deleted file mode 100644
index fefcf38c61..0000000000
--- a/libs/gst/check/libcheck/libcompat/libcompat.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-/* silence warnings about an empty library */
-void
-ck_do_nothing (void)
-{
- assert (0);
-
- /*
- * to silence warning about this function actually
- * returning, but being marked as noreturn. assert()
- * must be marked as a function that returns.
- */
- exit (1);
-}
diff --git a/libs/gst/check/libcheck/libcompat/libcompat.h b/libs/gst/check/libcheck/libcompat/libcompat.h
deleted file mode 100644
index b88121bcf2..0000000000
--- a/libs/gst/check/libcheck/libcompat/libcompat.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef LIBCOMPAT_H
-#define LIBCOMPAT_H
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-#define GCC_VERSION_AT_LEAST(major, minor) \
-((__GNUC__ > (major)) || \
- (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
-#else
-#define GCC_VERSION_AT_LEAST(major, minor) 0
-#endif
-
-#if GCC_VERSION_AT_LEAST(2,95)
-#define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
-#else
-#define CK_ATTRIBUTE_UNUSED
-#endif /* GCC 2.95 */
-
-#if GCC_VERSION_AT_LEAST(2,5)
-#define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
-#else
-#define CK_ATTRIBUTE_NORETURN
-#endif /* GCC 2.5 */
-
-/*
- * Used for MSVC to create the export attribute
- * CK_DLL_EXP is defined during the compilation of the library
- * on the command line.
- */
-#ifndef CK_DLL_EXP
-#define CK_DLL_EXP extern
-#endif
-
-#if _MSC_VER
-#include <WinSock2.h> /* struct timeval, API used in gettimeofday implementation */
-#include <io.h> /* read, write */
-#include <process.h> /* getpid */
-#include <BaseTsd.h> /* for ssize_t */
-typedef SSIZE_T ssize_t;
-#endif /* _MSC_VER */
-
-/* defines size_t */
-#include <sys/types.h>
-
-/* provides assert */
-#include <assert.h>
-
-/* defines FILE */
-#include <stdio.h>
-
-/* defines exit() */
-#include <stdlib.h>
-
-/* provides localtime and struct tm */
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif /* !HAVE_SYS_TIME_H */
-#include <time.h>
-
-/* declares fork(), _POSIX_VERSION. according to Autoconf.info,
- unistd.h defines _POSIX_VERSION if the system is POSIX-compliant,
- so we will use this as a test for all things uniquely provided by
- POSIX like sigaction() and fork() */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-/* declares pthread_create and friends */
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-/* replacement functions for broken originals */
-#if !HAVE_DECL_ALARM
-CK_DLL_EXP unsigned int alarm (unsigned int seconds);
-#endif /* !HAVE_DECL_ALARM */
-
-#if !HAVE_MALLOC
-CK_DLL_EXP void *rpl_malloc (size_t n);
-#endif /* !HAVE_MALLOC */
-
-#if !HAVE_REALLOC
-CK_DLL_EXP void *rpl_realloc (void *p, size_t n);
-#endif /* !HAVE_REALLOC */
-
-#if !HAVE_GETPID && HAVE__GETPID
-#define getpid _getpid
-#endif /* !HAVE_GETPID && HAVE__GETPID */
-
-#if !HAVE_GETTIMEOFDAY
-CK_DLL_EXP int gettimeofday (struct timeval *tv, void *tz);
-#endif /* !HAVE_GETTIMEOFDAY */
-
-#if !HAVE_DECL_LOCALTIME_R
-#if !defined(localtime_r)
-CK_DLL_EXP struct tm *localtime_r (const time_t * clock, struct tm *result);
-#endif
-#endif /* !HAVE_DECL_LOCALTIME_R */
-
-#if !HAVE_DECL_STRDUP && !HAVE__STRDUP
-CK_DLL_EXP char *strdup (const char *str);
-#elif !HAVE_DECL_STRDUP && HAVE__STRDUP
-#define strdup _strdup
-#endif /* !HAVE_DECL_STRDUP && HAVE__STRDUP */
-
-#if !HAVE_DECL_STRSIGNAL
-CK_DLL_EXP char *strsignal (int sig);
-#endif /* !HAVE_DECL_STRSIGNAL */
-
-/*
- * On systems where clock_gettime() is not available, or
- * on systems where some clocks may not be supported, the
- * definition for CLOCK_MONOTONIC and CLOCK_REALTIME may not
- * be available. These should define which type of clock
- * clock_gettime() should use. We define it here if it is
- * not defined simply so the reimplementation can ignore it.
- *
- * We set the values of these clocks to some (hopefully)
- * invalid value, to avoid the case where we define a
- * clock with a valid value, and unintentionally use
- * an actual good clock by accident.
- */
-#ifndef CLOCK_MONOTONIC
-#define CLOCK_MONOTONIC -1
-#endif
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME -1
-#endif
-
-#ifndef HAVE_LIBRT
-
-#ifdef STRUCT_TIMESPEC_DEFINITION_MISSING
-/*
- * The following structure is defined in POSIX 1003.1 for times
- * specified in seconds and nanoseconds. If it is not defined in
- * time.g, then we need to define it here
- */
-struct timespec
-{
- time_t tv_sec;
- long tv_nsec;
-};
-#endif /* STRUCT_TIMESPEC_DEFINITION_MISSING */
-
-#ifdef STRUCT_ITIMERSPEC_DEFINITION_MISSING
-/*
- * The following structure is defined in POSIX.1b for timer start values and intervals.
- * If it is not defined in time.h, then we need to define it here.
- */
-struct itimerspec
-{
- struct timespec it_interval;
- struct timespec it_value;
-};
-#endif /* STRUCT_ITIMERSPEC_DEFINITION_MISSING */
-
-/*
- * Do a simple forward declaration in case the struct is not defined.
- * In the versions of timer_create in libcompat, sigevent is never
- * used.
- */
-struct sigevent;
-
-#ifndef HAVE_CLOCK_GETTIME
-CK_DLL_EXP int clock_gettime (clockid_t clk_id, struct timespec *ts);
-#endif
-CK_DLL_EXP int timer_create (clockid_t clockid, struct sigevent *sevp,
- timer_t * timerid);
-CK_DLL_EXP int timer_settime (timer_t timerid, int flags,
- const struct itimerspec *new_value, struct itimerspec *old_value);
-CK_DLL_EXP int timer_delete (timer_t timerid);
-#endif /* HAVE_LIBRT */
-
-/*
- * The following checks are to determine if the system's
- * snprintf (or its variants) should be replaced with
- * the C99 compliant version in libcompat.
- */
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-#if HAVE_STDARG_H
-#include <stdarg.h>
-
-#if !HAVE_VSNPRINTF
-CK_DLL_EXP int rpl_vsnprintf (char *, size_t, const char *, va_list);
-
-#define vsnprintf rpl_vsnprintf
-#endif
-#if !HAVE_SNPRINTF
-CK_DLL_EXP int rpl_snprintf (char *, size_t, const char *, ...);
-
-#define snprintf rpl_snprintf
-#endif
-#endif /* HAVE_STDARG_H */
-
-#if !HAVE_GETLINE
-CK_DLL_EXP ssize_t getline (char **lineptr, size_t * n, FILE * stream);
-#endif
-
-/* silence warnings about an empty library */
-CK_DLL_EXP void
-ck_do_nothing (void)
- CK_ATTRIBUTE_NORETURN;
-
-#endif /* !LIBCOMPAT_H */
diff --git a/libs/gst/check/libcheck/libcompat/localtime_r.c b/libs/gst/check/libcheck/libcompat/localtime_r.c
deleted file mode 100644
index 06ac582f86..0000000000
--- a/libs/gst/check/libcheck/libcompat/localtime_r.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-#if !defined(localtime_r)
-
-struct tm *
-localtime_r (const time_t * clock, struct tm *result)
-{
- struct tm *now = localtime (clock);
-
- if (now == NULL) {
- return NULL;
- } else {
- *result = *now;
- }
-
- return result;
-}
-
-#endif /* !defined(localtime_r) */
diff --git a/libs/gst/check/libcheck/libcompat/strdup.c b/libs/gst/check/libcheck/libcompat/strdup.c
deleted file mode 100644
index 1d6aa61a81..0000000000
--- a/libs/gst/check/libcheck/libcompat/strdup.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-char *
-strdup (const char *str CK_ATTRIBUTE_UNUSED)
-{
- assert (0);
- return NULL;
-}
diff --git a/libs/gst/check/libcheck/libcompat/strsignal.c b/libs/gst/check/libcheck/libcompat/strsignal.c
deleted file mode 100644
index fd93ad5037..0000000000
--- a/libs/gst/check/libcheck/libcompat/strsignal.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-char *
-strsignal (int sig)
-{
- static char signame[40];
-
- sprintf (signame, "SIG #%d", sig);
- return signame;
-}
diff --git a/libs/gst/check/libcheck/libcompat/timer_create.c b/libs/gst/check/libcheck/libcompat/timer_create.c
deleted file mode 100644
index 2e250f0d08..0000000000
--- a/libs/gst/check/libcheck/libcompat/timer_create.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-int
-timer_create (clockid_t clockid CK_ATTRIBUTE_UNUSED,
- struct sigevent *sevp CK_ATTRIBUTE_UNUSED,
- timer_t * timerid CK_ATTRIBUTE_UNUSED)
-{
- /*
- * The create function does nothing. timer_settime will use
- * alarm to set the timer, and timer_delete will stop the
- * alarm
- */
-
- return 0;
-}
diff --git a/libs/gst/check/libcheck/libcompat/timer_delete.c b/libs/gst/check/libcheck/libcompat/timer_delete.c
deleted file mode 100644
index 5740bd65dc..0000000000
--- a/libs/gst/check/libcheck/libcompat/timer_delete.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-int
-timer_delete (timer_t timerid CK_ATTRIBUTE_UNUSED)
-{
-#ifdef HAVE_SETITIMER
- /*
- * If the system does not have timer_settime() but does have
- * setitimer() use that instead of alarm().
- */
- struct itimerval interval;
-
- /*
- * Setting values to '0' results in disabling the running timer.
- */
- interval.it_value.tv_sec = 0;
- interval.it_value.tv_usec = 0;
- interval.it_interval.tv_sec = 0;
- interval.it_interval.tv_usec = 0;
-
- return setitimer (ITIMER_REAL, &interval, NULL);
-#else
- /*
- * There is only one timer, that used by alarm.
- * Setting alarm(0) will not set a new alarm, and
- * will kill the previous timer.
- */
-
- alarm (0);
-
- return 0;
-#endif
-}
diff --git a/libs/gst/check/libcheck/libcompat/timer_settime.c b/libs/gst/check/libcheck/libcompat/timer_settime.c
deleted file mode 100644
index db2b1d597a..0000000000
--- a/libs/gst/check/libcheck/libcompat/timer_settime.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Check: a unit test framework for C
- * Copyright (C) 2001, 2002 Arien Malec
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "libcompat.h"
-
-int
-timer_settime (timer_t timerid CK_ATTRIBUTE_UNUSED,
- int flags CK_ATTRIBUTE_UNUSED,
- const struct itimerspec *new_value,
- struct itimerspec *old_value CK_ATTRIBUTE_UNUSED)
-{
-#ifdef HAVE_SETITIMER
- /*
- * If the system does not have timer_settime() but does have
- * setitimer() use that instead of alarm().
- */
- struct itimerval interval;
-
- interval.it_value.tv_sec = new_value->it_value.tv_sec;
- interval.it_value.tv_usec = new_value->it_value.tv_nsec / 1000;
- interval.it_interval.tv_sec = new_value->it_interval.tv_sec;
- interval.it_interval.tv_usec = new_value->it_interval.tv_nsec / 1000;
-
- return setitimer (ITIMER_REAL, &interval, NULL);
-#else
- int seconds = new_value->it_value.tv_sec;
-
- /*
- * As the alarm() call has only second precision, if the caller
- * specifies partial seconds, we round up to the nearest second.
- */
- if (new_value->it_value.tv_nsec > 0) {
- seconds += 1;
- }
-
- alarm (seconds);
-
- return 0;
-#endif
-}
diff --git a/libs/gst/check/libcheck/meson.build b/libs/gst/check/libcheck/meson.build
deleted file mode 100644
index c6d496d182..0000000000
--- a/libs/gst/check/libcheck/meson.build
+++ /dev/null
@@ -1,91 +0,0 @@
-libcheck_files = [
- 'check.c',
- 'check_error.c',
- 'check_list.c',
- 'check_log.c',
- 'check_msg.c',
- 'check_pack.c',
- 'check_print.c',
- 'check_run.c',
- 'check_str.c',
- 'libcompat/libcompat.c'
-]
-
-if not cdata.has('HAVE_ALARM')
- libcheck_files += ['libcompat/alarm.c']
-endif
-
-if not cdata.has('HAVE_GETTIMEOFDAY')
- libcheck_files += ['libcompat/gettimeofday.c']
-endif
-
-if not cdata.has('HAVE_CLOCK_GETTIME')
- libcheck_files += ['libcompat/clock_gettime.c']
-endif
-
-if not cdata.has('HAVE_DECL_LOCALTIME_R')
- libcheck_files += ['libcompat/localtime_r.c']
-endif
-
-if not cdata.has('HAVE_DECL_STRSIGNAL')
- libcheck_files += ['libcompat/strsignal.c']
-endif
-
-if not cdata.has('HAVE_DECL_STRDUP') and not cdata.has('HAVE__STRDUP')
- libcheck_files += ['libcompat/strdup.c']
-endif
-
-if not cdata.has('HAVE_GETLINE')
- libcheck_files += ['libcompat/getline.c']
-endif
-
-# FIXME: check that timer_create, timer_settime, timer_delete are in rt_lib
-if not rt_lib.found()
- libcheck_files += [
- 'libcompat/timer_create.c',
- 'libcompat/timer_settime.c',
- 'libcompat/timer_delete.c'
- ]
-endif
-
-configure_file(input : 'check.h.in',
- output : 'check.h',
- configuration : check_cdata)
-
-internal_check_h_inc = include_directories('..')
-
-# Must explicitly make symbols public if default visibility is hidden
-if have_visibility_hidden
- libcheck_visibility_args = ['-DCK_DLL_EXP=extern __attribute__ ((visibility ("default")))']
-else
- if host_system == 'windows'
- libcheck_visibility_args = ['-DCK_DLL_EXP=__declspec(dllexport)']
- else
- libcheck_visibility_args = ['-DCK_DLL_EXP=extern']
- endif
-endif
-
-no_warn_args = []
-foreach arg : [
- '-Wno-undef',
- '-Wno-redundant-decls',
- '-Wno-missing-prototypes',
- '-Wno-missing-declarations',
- '-Wno-old-style-definition',
- '-Wno-declaration-after-statement',
- '-Wno-format-nonliteral',
- '-Wno-tautological-constant-out-of-range-compare']
- if cc.has_argument(arg)
- no_warn_args += [arg]
- endif
-endforeach
-
-libcheck = static_library('check',
- libcheck_files,
- include_directories : [configinc, internal_check_h_inc],
- dependencies : [rt_lib, mathlib, glib_dep],
- c_args: gst_c_args + libcheck_visibility_args + no_warn_args +
- # Don't want libcompat to think we don't have these and substitute
- # replacements since we don't check for or define these. See libcompat.h
- ['-DHAVE_VSNPRINTF', '-DHAVE_SNPRINTF', '-DHAVE_MALLOC', '-DHAVE_REALLOC'],
- pic: true)
diff --git a/libs/gst/check/meson.build b/libs/gst/check/meson.build
deleted file mode 100644
index 316465a350..0000000000
--- a/libs/gst/check/meson.build
+++ /dev/null
@@ -1,88 +0,0 @@
-gst_check_sources = [
- 'gstbufferstraw.c',
- 'gstcheck.c',
- 'gstconsistencychecker.c',
- 'gstharness.c',
- 'gsttestclock.c',
-]
-gst_check_headers = [
- 'check.h',
- 'check-prelude.h',
- 'gstbufferstraw.h',
- 'gstcheck.h',
- 'gstconsistencychecker.h',
- 'gstharness.h',
- 'gsttestclock.h',
-]
-install_headers(gst_check_headers, subdir : 'gstreamer-1.0/gst/check/')
-
-
-check_cdata = configuration_data()
-
-check_cdata.set('ENABLE_SUBUNIT', 0)
-check_cdata.set('CHECK_MAJOR_VERSION', 0)
-check_cdata.set('CHECK_MINOR_VERSION', 9)
-check_cdata.set('CHECK_MICRO_VERSION', 14)
-if host_system != 'windows'
- check_cdata.set('HAVE_FORK', 1)
-else
- check_cdata.set('HAVE_FORK', 0)
-endif
-
-subdir('libcheck')
-
-configure_file(input : 'libcheck/check.h.in',
- output : 'internal-check.h',
- install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst/check'),
- configuration : check_cdata)
-
-gst_check = library('gstcheck-@0@'.format(apiversion),
- gst_check_sources,
- c_args : gst_c_args + ['-UG_DISABLE_ASSERT', '-DBUILDING_GST_CHECK'],
- version : libversion,
- soversion : soversion,
- darwin_versions : osxversion,
- install : true,
- include_directories : [configinc, libsinc],
- link_with : [libcheck],
- dependencies : [gobject_dep, glib_dep, gst_dep],
-)
-
-pkgconfig.generate(gst_check,
- libraries : [libgst],
- # FIXME: Add manually libcheck's dependencies because it's an uninstalled static
- # library and Meson <0.56.0 does not handle them correctly.
- # See https://github.com/mesonbuild/meson/pull/7488.
- libraries_private: [rt_lib, mathlib],
- variables : pkgconfig_variables,
- subdirs : pkgconfig_subdirs,
- name : 'gstreamer-check-1.0',
- description : 'Unit testing helper library for GStreamer modules',
-)
-
-gst_check_gen_sources = []
-
-if build_gir
- gst_gir_extra_args = gir_init_section + [ '--c-include=gst/check/check.h' ]
- gst_check_gir = gnome.generate_gir(gst_check,
- sources : gst_check_sources + gst_check_headers,
- namespace : 'GstCheck',
- nsversion : apiversion,
- identifier_prefix : 'Gst',
- symbol_prefix : 'gst',
- export_packages : 'gstreamer-check-1.0',
- dependencies : [gst_dep],
- include_directories : [configinc, libsinc, privinc],
- includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
- install : true,
- extra_args : gst_gir_extra_args,
- )
- gst_check_gen_sources += gst_check_gir
-endif
-
-gst_check_dep = declare_dependency(link_with : gst_check,
- include_directories : [libsinc],
- dependencies : [gst_dep],
- sources : gst_check_gen_sources)
-
-meson.override_dependency('gstreamer-check-1.0', gst_check_dep)
diff --git a/libs/gst/controller/controller-prelude.h b/libs/gst/controller/controller-prelude.h
deleted file mode 100644
index cd7f0c9196..0000000000
--- a/libs/gst/controller/controller-prelude.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* GStreamer Controller Library
- * Copyright (C) 2018 GStreamer developers
- *
- * controller-prelude.h: prelude include header for gst-controller library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CONTROLLER_PRELUDE_H__
-#define __GST_CONTROLLER_PRELUDE_H__
-
-#include <gst/gst.h>
-
-#ifndef GST_CONTROLLER_API
-#ifdef BUILDING_GST_CONTROLLER
-#define GST_CONTROLLER_API GST_API_EXPORT /* from config.h */
-#else
-#define GST_CONTROLLER_API GST_API_IMPORT
-#endif
-#endif
-
-#endif /* __GST_CONTROLLER_PRELUDE_H__ */
diff --git a/libs/gst/controller/controller.h b/libs/gst/controller/controller.h
deleted file mode 100644
index 79ae8ce6da..0000000000
--- a/libs/gst/controller/controller.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* GStreamer
- * Copyright (C) 2012 GStreamer developers
- *
- * gstcontroller.h: single include header for gst-controller library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_CONTROLLER_H__
-#define __GST_CONTROLLER_H__
-
-#include <gst/controller/controller-prelude.h>
-
-#include <gst/controller/gstargbcontrolbinding.h>
-#include <gst/controller/gstdirectcontrolbinding.h>
-#include <gst/controller/gstproxycontrolbinding.h>
-#include <gst/controller/gsttimedvaluecontrolsource.h>
-#include <gst/controller/gstinterpolationcontrolsource.h>
-#include <gst/controller/gsttriggercontrolsource.h>
-#include <gst/controller/gstlfocontrolsource.h>
-
-#endif /* __GST_CONTROLLER_H__ */
diff --git a/libs/gst/controller/gstargbcontrolbinding.c b/libs/gst/controller/gstargbcontrolbinding.c
deleted file mode 100644
index b8014a0db9..0000000000
--- a/libs/gst/controller/gstargbcontrolbinding.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gstargbcontrolbinding.c: Attachment for multiple control sources to gargb
- * properties
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstargbcontrolbinding
- * @title: GstARGBControlBinding
- * @short_description: attachment for control sources to argb properties
- *
- * A value mapping object that attaches multiple control sources to a guint
- * gobject properties representing a color. A control value of 0.0 will turn the
- * color component off and a value of 1.0 will be the color level.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include "gstargbcontrolbinding.h"
-
-#include <gst/math-compat.h>
-
-#define GST_CAT_DEFAULT control_binding_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-static GObject *gst_argb_control_binding_constructor (GType type,
- guint n_construct_params, GObjectConstructParam * construct_params);
-static void gst_argb_control_binding_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_argb_control_binding_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_argb_control_binding_dispose (GObject * object);
-static void gst_argb_control_binding_finalize (GObject * object);
-
-static gboolean gst_argb_control_binding_sync_values (GstControlBinding * _self,
- GstObject * object, GstClockTime timestamp, GstClockTime last_sync);
-static GValue *gst_argb_control_binding_get_value (GstControlBinding * _self,
- GstClockTime timestamp);
-static gboolean gst_argb_control_binding_get_value_array (GstControlBinding *
- _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
- gpointer values);
-static gboolean gst_argb_control_binding_get_g_value_array (GstControlBinding *
- _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
- GValue * values);
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstargbcontrolbinding", 0, \
- "dynamic parameter control source attachment");
-
-#define gst_argb_control_binding_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstARGBControlBinding, gst_argb_control_binding,
- GST_TYPE_CONTROL_BINDING, _do_init);
-
-enum
-{
- PROP_0,
- PROP_CS_A,
- PROP_CS_R,
- PROP_CS_G,
- PROP_CS_B,
- PROP_LAST
-};
-
-static GParamSpec *properties[PROP_LAST];
-
-/* vmethods */
-
-static void
-gst_argb_control_binding_class_init (GstARGBControlBindingClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstControlBindingClass *control_binding_class =
- GST_CONTROL_BINDING_CLASS (klass);
-
- gobject_class->constructor = gst_argb_control_binding_constructor;
- gobject_class->set_property = gst_argb_control_binding_set_property;
- gobject_class->get_property = gst_argb_control_binding_get_property;
- gobject_class->dispose = gst_argb_control_binding_dispose;
- gobject_class->finalize = gst_argb_control_binding_finalize;
-
- control_binding_class->sync_values = gst_argb_control_binding_sync_values;
- control_binding_class->get_value = gst_argb_control_binding_get_value;
- control_binding_class->get_value_array =
- gst_argb_control_binding_get_value_array;
- control_binding_class->get_g_value_array =
- gst_argb_control_binding_get_g_value_array;
-
- properties[PROP_CS_A] =
- g_param_spec_object ("control-source-a", "ControlSource A",
- "The control source for the alpha color component",
- GST_TYPE_CONTROL_SOURCE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_CS_R] =
- g_param_spec_object ("control-source-r", "ControlSource R",
- "The control source for the red color component",
- GST_TYPE_CONTROL_SOURCE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_CS_G] =
- g_param_spec_object ("control-source-g", "ControlSource G",
- "The control source for the green color component",
- GST_TYPE_CONTROL_SOURCE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_CS_B] =
- g_param_spec_object ("control-source-b", "ControlSource B",
- "The control source for the blue color component",
- GST_TYPE_CONTROL_SOURCE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (gobject_class, PROP_LAST, properties);
-}
-
-static void
-gst_argb_control_binding_init (GstARGBControlBinding * self)
-{
-}
-
-static GObject *
-gst_argb_control_binding_constructor (GType type, guint n_construct_params,
- GObjectConstructParam * construct_params)
-{
- GstARGBControlBinding *self;
-
- self =
- GST_ARGB_CONTROL_BINDING (G_OBJECT_CLASS (parent_class)->constructor
- (type, n_construct_params, construct_params));
-
- if (GST_CONTROL_BINDING_PSPEC (self)) {
- if (!(G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self)) ==
- G_TYPE_UINT)) {
- GST_WARNING ("can't bind to paramspec type '%s'",
- G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self)));
- GST_CONTROL_BINDING_PSPEC (self) = NULL;
- } else {
- g_value_init (&self->cur_value, G_TYPE_UINT);
- }
- }
- return (GObject *) self;
-}
-
-static void
-gst_argb_control_binding_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object);
-
- switch (prop_id) {
- case PROP_CS_A:
- gst_object_replace ((GstObject **) & self->cs_a,
- g_value_get_object (value));
- break;
- case PROP_CS_R:
- gst_object_replace ((GstObject **) & self->cs_r,
- g_value_get_object (value));
- break;
- case PROP_CS_G:
- gst_object_replace ((GstObject **) & self->cs_g,
- g_value_get_object (value));
- break;
- case PROP_CS_B:
- gst_object_replace ((GstObject **) & self->cs_b,
- g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_argb_control_binding_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object);
-
- switch (prop_id) {
- case PROP_CS_A:
- g_value_set_object (value, self->cs_a);
- break;
- case PROP_CS_R:
- g_value_set_object (value, self->cs_r);
- break;
- case PROP_CS_G:
- g_value_set_object (value, self->cs_g);
- break;
- case PROP_CS_B:
- g_value_set_object (value, self->cs_b);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_argb_control_binding_dispose (GObject * object)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object);
-
- gst_object_replace ((GstObject **) & self->cs_a, NULL);
- gst_object_replace ((GstObject **) & self->cs_r, NULL);
- gst_object_replace ((GstObject **) & self->cs_g, NULL);
- gst_object_replace ((GstObject **) & self->cs_b, NULL);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-gst_argb_control_binding_finalize (GObject * object)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object);
-
- g_value_unset (&self->cur_value);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_argb_control_binding_sync_values (GstControlBinding * _self,
- GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
- gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0;
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT,
- _self->name, GST_TIME_ARGS (timestamp));
-
- if (self->cs_a)
- ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a);
- if (self->cs_r)
- ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r);
- if (self->cs_g)
- ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g);
- if (self->cs_b)
- ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b);
- if (G_LIKELY (ret)) {
- guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) |
- (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) |
- (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) |
- ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255));
- GST_LOG_OBJECT (object, " new value 0x%08x", src_val);
- /* always set the value for first time, but then only if it changed
- * this should limit g_object_notify invocations.
- * FIXME: can we detect negative playback rates?
- */
- if ((timestamp < last_sync) || (src_val != self->last_value)) {
- GValue *dst_val = &self->cur_value;
-
- g_value_set_uint (dst_val, src_val);
- /* we can make this faster
- * http://bugzilla.gnome.org/show_bug.cgi?id=536939
- */
- g_object_set_property ((GObject *) object, _self->name, dst_val);
- self->last_value = src_val;
- }
- } else {
- GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name);
- }
- return (ret);
-}
-
-static GValue *
-gst_argb_control_binding_get_value (GstControlBinding * _self,
- GstClockTime timestamp)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
- GValue *dst_val = NULL;
- gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0;
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), NULL);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- /* get current value via control source */
- if (self->cs_a)
- ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a);
- if (self->cs_r)
- ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r);
- if (self->cs_g)
- ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g);
- if (self->cs_b)
- ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b);
- if (G_LIKELY (ret)) {
- guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) |
- (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) |
- (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) |
- ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255));
- dst_val = g_new0 (GValue, 1);
- g_value_init (dst_val, G_TYPE_UINT);
- g_value_set_uint (dst_val, src_val);
- } else {
- GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT,
- _self->name, GST_TIME_ARGS (timestamp));
- }
-
- return dst_val;
-}
-
-static gboolean
-gst_argb_control_binding_get_value_array (GstControlBinding * _self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gpointer values_)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
- gint i;
- gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b =
- NULL;
- guint *values = (guint *) values_;
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
- g_return_val_if_fail (values, FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- if (self->cs_a) {
- src_val_a = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_a, timestamp,
- interval, n_values, src_val_a);
- }
- if (self->cs_r) {
- src_val_r = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_r, timestamp,
- interval, n_values, src_val_r);
- }
- if (self->cs_g) {
- src_val_g = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_g, timestamp,
- interval, n_values, src_val_g);
- }
- if (self->cs_b) {
- src_val_b = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_b, timestamp,
- interval, n_values, src_val_b);
- }
- if (G_LIKELY (ret)) {
- for (i = 0; i < n_values; i++) {
- gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0;
- if (src_val_a && !isnan (src_val_a[i]))
- a = src_val_a[i];
- if (src_val_r && !isnan (src_val_r[i]))
- r = src_val_r[i];
- if (src_val_g && !isnan (src_val_g[i]))
- g = src_val_g[i];
- if (src_val_b && !isnan (src_val_b[i]))
- b = src_val_b[i];
- values[i] = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) |
- (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) |
- (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) |
- ((guint) (CLAMP (b, 0.0, 1.0) * 255));
- }
- } else {
- GST_LOG ("failed to get control value for property %s at ts %"
- GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
- }
- g_free (src_val_a);
- g_free (src_val_r);
- g_free (src_val_g);
- g_free (src_val_b);
- return ret;
-}
-
-static gboolean
-gst_argb_control_binding_get_g_value_array (GstControlBinding * _self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- GValue * values)
-{
- GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
- gint i;
- gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b =
- NULL;
- guint src_val;
- gboolean ret = TRUE;
-
- g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
- g_return_val_if_fail (values, FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- if (self->cs_a) {
- src_val_a = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_a, timestamp,
- interval, n_values, src_val_a);
- }
- if (self->cs_r) {
- src_val_r = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_r, timestamp,
- interval, n_values, src_val_r);
- }
- if (self->cs_g) {
- src_val_g = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_g, timestamp,
- interval, n_values, src_val_g);
- }
- if (self->cs_b) {
- src_val_b = g_new0 (gdouble, n_values);
- ret &= gst_control_source_get_value_array (self->cs_b, timestamp,
- interval, n_values, src_val_b);
- }
- if (G_LIKELY (ret)) {
- for (i = 0; i < n_values; i++) {
- gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0;
- if (src_val_a && !isnan (src_val_a[i]))
- a = src_val_a[i];
- if (src_val_r && !isnan (src_val_r[i]))
- r = src_val_r[i];
- if (src_val_g && !isnan (src_val_g[i]))
- g = src_val_g[i];
- if (src_val_b && !isnan (src_val_b[i]))
- b = src_val_b[i];
- src_val = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) |
- (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) |
- (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) |
- ((guint) (CLAMP (b, 0.0, 1.0) * 255));
- g_value_init (&values[i], G_TYPE_UINT);
- g_value_set_uint (&values[i], src_val);
- }
- } else {
- GST_LOG ("failed to get control value for property %s at ts %"
- GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
- }
- g_free (src_val_a);
- g_free (src_val_r);
- g_free (src_val_g);
- g_free (src_val_b);
- return ret;
-}
-
-/* functions */
-
-/**
- * gst_argb_control_binding_new:
- * @object: the object of the property
- * @property_name: the property-name to attach the control source
- * @cs_a: the control source for the alpha channel
- * @cs_r: the control source for the red channel
- * @cs_g: the control source for the green channel
- * @cs_b: the control source for the blue channel
- *
- * Create a new control-binding that attaches the given #GstControlSource to the
- * #GObject property.
- *
- * Returns: (transfer floating): the new #GstARGBControlBinding
- */
-GstControlBinding *
-gst_argb_control_binding_new (GstObject * object, const gchar * property_name,
- GstControlSource * cs_a, GstControlSource * cs_r, GstControlSource * cs_g,
- GstControlSource * cs_b)
-{
- return (GstControlBinding *) g_object_new (GST_TYPE_ARGB_CONTROL_BINDING,
- "object", object, "name", property_name,
- "control-source-a", cs_a,
- "control-source-r", cs_r,
- "control-source-g", cs_g, "control-source-b", cs_b, NULL);
-}
-
-/* functions */
diff --git a/libs/gst/controller/gstargbcontrolbinding.h b/libs/gst/controller/gstargbcontrolbinding.h
deleted file mode 100644
index 3d1c8baacd..0000000000
--- a/libs/gst/controller/gstargbcontrolbinding.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gstargbcontrolbinding.h: Attachment for multiple control sources to gargb
- * properties
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_ARGB_CONTROL_BINDING_H__
-#define __GST_ARGB_CONTROL_BINDING_H__
-
-#include <gst/gstconfig.h>
-
-#include <glib-object.h>
-
-#include <gst/gstcontrolsource.h>
-#include <gst/controller/controller-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_ARGB_CONTROL_BINDING \
- (gst_argb_control_binding_get_type())
-#define GST_ARGB_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ARGB_CONTROL_BINDING,GstARGBControlBinding))
-#define GST_ARGB_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ARGB_CONTROL_BINDING,GstARGBControlBindingClass))
-#define GST_IS_ARGB_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ARGB_CONTROL_BINDING))
-#define GST_IS_ARGB_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ARGB_CONTROL_BINDING))
-#define GST_ARGB_CONTROL_BINDING_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstARGBControlBindingClass))
-
-typedef struct _GstARGBControlBinding GstARGBControlBinding;
-typedef struct _GstARGBControlBindingClass GstARGBControlBindingClass;
-
-/**
- * GstARGBControlBinding:
- * @name: name of the property of this binding
- *
- * The instance structure of #GstARGBControlBinding.
- */
-struct _GstARGBControlBinding {
- GstControlBinding parent;
-
- /*< private >*/
- GstControlSource *cs_a; /* GstControlSources for this property */
- GstControlSource *cs_r;
- GstControlSource *cs_g;
- GstControlSource *cs_b;
-
- GValue cur_value;
- guint32 last_value;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstARGBControlBindingClass:
- * @parent_class: Parent class
- * @convert: Class method to convert control-values
- *
- * The class structure of #GstARGBControlBinding.
- */
-
-struct _GstARGBControlBindingClass
-{
- GstControlBindingClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_argb_control_binding_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GstControlBinding * gst_argb_control_binding_new (GstObject * object, const gchar * property_name,
- GstControlSource * cs_a, GstControlSource * cs_r,
- GstControlSource * cs_g, GstControlSource * cs_b);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstARGBControlBinding, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_ARGB_CONTROL_BINDING_H__ */
diff --git a/libs/gst/controller/gstdirectcontrolbinding.c b/libs/gst/controller/gstdirectcontrolbinding.c
deleted file mode 100644
index 0c4d589f4b..0000000000
--- a/libs/gst/controller/gstdirectcontrolbinding.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gstdirectcontrolbinding.c: Direct attachment for control sources
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstdirectcontrolbinding
- * @title: GstDirectControlBinding
- * @short_description: direct attachment for control sources
- *
- * A value mapping object that attaches control sources to gobject properties. It
- * will map the control values directly to the target property range. If a
- * non-absolute direct control binding is used, the value range [0.0 ... 1.0]
- * is mapped to full target property range, and all values outside the range
- * will be clipped. An absolute control binding will not do any value
- * transformations.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include "gstdirectcontrolbinding.h"
-
-#include <gst/math-compat.h>
-
-#define GST_CAT_DEFAULT control_binding_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-
-static GObject *gst_direct_control_binding_constructor (GType type,
- guint n_construct_params, GObjectConstructParam * construct_params);
-static void gst_direct_control_binding_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_direct_control_binding_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_direct_control_binding_dispose (GObject * object);
-static void gst_direct_control_binding_finalize (GObject * object);
-
-static gboolean gst_direct_control_binding_sync_values (GstControlBinding *
- _self, GstObject * object, GstClockTime timestamp, GstClockTime last_sync);
-static GValue *gst_direct_control_binding_get_value (GstControlBinding * _self,
- GstClockTime timestamp);
-static gboolean gst_direct_control_binding_get_value_array (GstControlBinding *
- _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
- gpointer values);
-static gboolean gst_direct_control_binding_get_g_value_array (GstControlBinding
- * _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
- GValue * values);
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstdirectcontrolbinding", 0, \
- "dynamic parameter control source attachment");
-
-#define gst_direct_control_binding_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstDirectControlBinding, gst_direct_control_binding,
- GST_TYPE_CONTROL_BINDING, _do_init);
-
-enum
-{
- PROP_0,
- PROP_CS,
- PROP_ABSOLUTE,
- PROP_LAST
-};
-
-static GParamSpec *properties[PROP_LAST];
-
-/* mapping functions */
-
-#define DEFINE_CONVERT(type,Type,TYPE,ROUNDING_OP) \
-static void \
-convert_g_value_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \
-{ \
- GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \
- g##type v; \
- \
- s = CLAMP (s, 0.0, 1.0); \
- v = (g##type) ROUNDING_OP (pspec->minimum * (1-s)) + (g##type) ROUNDING_OP (pspec->maximum * s); \
- g_value_set_##type (d, v); \
-} \
-\
-static void \
-convert_value_to_##type (GstDirectControlBinding *self, gdouble s, gpointer d_) \
-{ \
- GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \
- g##type *d = (g##type *)d_; \
- \
- s = CLAMP (s, 0.0, 1.0); \
- *d = (g##type) ROUNDING_OP (pspec->minimum * (1-s)) + (g##type) ROUNDING_OP (pspec->maximum * s); \
-} \
-\
-static void \
-abs_convert_g_value_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \
-{ \
- g##type v; \
- v = (g##type) ROUNDING_OP (s); \
- g_value_set_##type (d, v); \
-} \
-\
-static void \
-abs_convert_value_to_##type (GstDirectControlBinding *self, gdouble s, gpointer d_) \
-{ \
- g##type *d = (g##type *)d_; \
- *d = (g##type) ROUNDING_OP (s); \
-}
-
-DEFINE_CONVERT (int, Int, INT, rint);
-DEFINE_CONVERT (uint, UInt, UINT, rint);
-DEFINE_CONVERT (long, Long, LONG, rint);
-DEFINE_CONVERT (ulong, ULong, ULONG, rint);
-DEFINE_CONVERT (int64, Int64, INT64, rint);
-DEFINE_CONVERT (uint64, UInt64, UINT64, rint);
-DEFINE_CONVERT (float, Float, FLOAT, /*NOOP*/);
-DEFINE_CONVERT (double, Double, DOUBLE, /*NOOP*/);
-
-static void
-convert_g_value_to_boolean (GstDirectControlBinding * self, gdouble s,
- GValue * d)
-{
- s = CLAMP (s, 0.0, 1.0);
- g_value_set_boolean (d, (gboolean) (s + 0.5));
-}
-
-static void
-convert_value_to_boolean (GstDirectControlBinding * self, gdouble s,
- gpointer d_)
-{
- gboolean *d = (gboolean *) d_;
-
- s = CLAMP (s, 0.0, 1.0);
- *d = (gboolean) (s + 0.5);
-}
-
-static void
-convert_g_value_to_enum (GstDirectControlBinding * self, gdouble s, GValue * d)
-{
- GParamSpecEnum *pspec =
- G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec);
- GEnumClass *e = pspec->enum_class;
- gint v;
-
- s = CLAMP (s, 0.0, 1.0);
- v = s * (e->n_values - 1);
- g_value_set_enum (d, e->values[v].value);
-}
-
-static void
-convert_value_to_enum (GstDirectControlBinding * self, gdouble s, gpointer d_)
-{
- GParamSpecEnum *pspec =
- G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec);
- GEnumClass *e = pspec->enum_class;
- gint *d = (gint *) d_;
-
- s = CLAMP (s, 0.0, 1.0);
- *d = e->values[(gint) (s * (e->n_values - 1))].value;
-}
-
-/* vmethods */
-
-static void
-gst_direct_control_binding_class_init (GstDirectControlBindingClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstControlBindingClass *control_binding_class =
- GST_CONTROL_BINDING_CLASS (klass);
-
- gobject_class->constructor = gst_direct_control_binding_constructor;
- gobject_class->set_property = gst_direct_control_binding_set_property;
- gobject_class->get_property = gst_direct_control_binding_get_property;
- gobject_class->dispose = gst_direct_control_binding_dispose;
- gobject_class->finalize = gst_direct_control_binding_finalize;
-
- control_binding_class->sync_values = gst_direct_control_binding_sync_values;
- control_binding_class->get_value = gst_direct_control_binding_get_value;
- control_binding_class->get_value_array =
- gst_direct_control_binding_get_value_array;
- control_binding_class->get_g_value_array =
- gst_direct_control_binding_get_g_value_array;
-
- properties[PROP_CS] =
- g_param_spec_object ("control-source", "ControlSource",
- "The control source",
- GST_TYPE_CONTROL_SOURCE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_ABSOLUTE] =
- g_param_spec_boolean ("absolute", "Absolute",
- "Whether the control values are absolute",
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (gobject_class, PROP_LAST, properties);
-}
-
-static void
-gst_direct_control_binding_init (GstDirectControlBinding * self)
-{
- self->last_value = G_MAXDOUBLE;
-}
-
-static GObject *
-gst_direct_control_binding_constructor (GType type, guint n_construct_params,
- GObjectConstructParam * construct_params)
-{
- GstDirectControlBinding *self;
-
- self =
- GST_DIRECT_CONTROL_BINDING (G_OBJECT_CLASS (parent_class)->constructor
- (type, n_construct_params, construct_params));
-
- if (GST_CONTROL_BINDING_PSPEC (self)) {
- GType type, base;
-
- base = type = G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self));
- g_value_init (&self->cur_value, type);
- while ((type = g_type_parent (type)))
- base = type;
-
- GST_DEBUG (" using type %s", g_type_name (base));
-
- /* select mapping function */
-
-#define SET_CONVERT_FUNCTION(type) \
- if (self->ABI.abi.want_absolute) { \
- self->convert_g_value = abs_convert_g_value_to_##type; \
- self->convert_value = abs_convert_value_to_##type; \
- } \
- else { \
- self->convert_g_value = convert_g_value_to_##type; \
- self->convert_value = convert_value_to_##type; \
- } \
- self->byte_size = sizeof (g##type);
-
-
- switch (base) {
- case G_TYPE_INT:
- SET_CONVERT_FUNCTION (int);
- break;
- case G_TYPE_UINT:
- SET_CONVERT_FUNCTION (uint);
- break;
- case G_TYPE_LONG:
- SET_CONVERT_FUNCTION (long);
- break;
- case G_TYPE_ULONG:
- SET_CONVERT_FUNCTION (ulong);
- break;
- case G_TYPE_INT64:
- SET_CONVERT_FUNCTION (int64);
- break;
- case G_TYPE_UINT64:
- SET_CONVERT_FUNCTION (uint64);
- break;
- case G_TYPE_FLOAT:
- SET_CONVERT_FUNCTION (float);
- break;
- case G_TYPE_DOUBLE:
- SET_CONVERT_FUNCTION (double);
- break;
- case G_TYPE_BOOLEAN:
- self->convert_g_value = convert_g_value_to_boolean;
- self->convert_value = convert_value_to_boolean;
- self->byte_size = sizeof (gboolean);
- break;
- case G_TYPE_ENUM:
- self->convert_g_value = convert_g_value_to_enum;
- self->convert_value = convert_value_to_enum;
- self->byte_size = sizeof (gint);
- break;
- default:
- GST_WARNING ("incomplete implementation for paramspec type '%s'",
- G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self)));
- GST_CONTROL_BINDING_PSPEC (self) = NULL;
- break;
- }
- }
- return (GObject *) self;
-}
-
-static void
-gst_direct_control_binding_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object);
-
- switch (prop_id) {
- case PROP_CS:
- self->cs = g_value_dup_object (value);
- break;
- case PROP_ABSOLUTE:
- self->ABI.abi.want_absolute = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_direct_control_binding_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object);
-
- switch (prop_id) {
- case PROP_CS:
- g_value_set_object (value, self->cs);
- break;
- case PROP_ABSOLUTE:
- g_value_set_boolean (value, self->ABI.abi.want_absolute);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_direct_control_binding_dispose (GObject * object)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object);
-
- if (self->cs)
- gst_object_replace ((GstObject **) & self->cs, NULL);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-gst_direct_control_binding_finalize (GObject * object)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object);
-
- if (G_IS_VALUE (&self->cur_value))
- g_value_unset (&self->cur_value);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_direct_control_binding_sync_values (GstControlBinding * _self,
- GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
- gdouble src_val;
- gboolean ret;
-
- g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT,
- _self->name, GST_TIME_ARGS (timestamp));
-
- ret = gst_control_source_get_value (self->cs, timestamp, &src_val);
- if (G_LIKELY (ret)) {
- GST_LOG_OBJECT (object, " new value %lf", src_val);
- /* always set the value for first time, but then only if it changed
- * this should limit g_object_notify invocations.
- * FIXME: can we detect negative playback rates?
- */
- if ((timestamp < last_sync) || (src_val != self->last_value)) {
- GValue *dst_val = &self->cur_value;
-
- GST_LOG_OBJECT (object, " mapping %s to value of type %s", _self->name,
- G_VALUE_TYPE_NAME (dst_val));
- /* run mapping function to convert gdouble to GValue */
- self->convert_g_value (self, src_val, dst_val);
- /* we can make this faster
- * http://bugzilla.gnome.org/show_bug.cgi?id=536939
- */
- g_object_set_property ((GObject *) object, _self->name, dst_val);
- self->last_value = src_val;
- }
- } else {
- GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name);
- }
- return (ret);
-}
-
-static GValue *
-gst_direct_control_binding_get_value (GstControlBinding * _self,
- GstClockTime timestamp)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
- GValue *dst_val = NULL;
- gdouble src_val;
-
- g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), NULL);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- /* get current value via control source */
- if (gst_control_source_get_value (self->cs, timestamp, &src_val)) {
- dst_val = g_new0 (GValue, 1);
- g_value_init (dst_val, G_PARAM_SPEC_VALUE_TYPE (_self->pspec));
- self->convert_g_value (self, src_val, dst_val);
- } else {
- GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT,
- _self->name, GST_TIME_ARGS (timestamp));
- }
-
- return dst_val;
-}
-
-static gboolean
-gst_direct_control_binding_get_value_array (GstControlBinding * _self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gpointer values_)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
- guint i;
- gdouble *src_val;
- gboolean res = FALSE;
- GstDirectControlBindingConvertValue convert;
- gint byte_size;
- guint8 *values = (guint8 *) values_;
-
- g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
- g_return_val_if_fail (values, FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- convert = self->convert_value;
- byte_size = self->byte_size;
-
- src_val = g_new0 (gdouble, n_values);
- if ((res = gst_control_source_get_value_array (self->cs, timestamp,
- interval, n_values, src_val))) {
- for (i = 0; i < n_values; i++) {
- /* we will only get NAN for sparse control sources, such as triggers */
- if (!isnan (src_val[i])) {
- convert (self, src_val[i], (gpointer) values);
- } else {
- GST_LOG ("no control value for property %s at index %d", _self->name,
- i);
- }
- values += byte_size;
- }
- } else {
- GST_LOG ("failed to get control value for property %s at ts %"
- GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
- }
- g_free (src_val);
- return res;
-}
-
-static gboolean
-gst_direct_control_binding_get_g_value_array (GstControlBinding * _self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- GValue * values)
-{
- GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
- guint i;
- gdouble *src_val;
- gboolean res = FALSE;
- GType type;
- GstDirectControlBindingConvertGValue convert;
-
- g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
- g_return_val_if_fail (values, FALSE);
- g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
-
- convert = self->convert_g_value;
- type = G_PARAM_SPEC_VALUE_TYPE (_self->pspec);
-
- src_val = g_new0 (gdouble, n_values);
- if ((res = gst_control_source_get_value_array (self->cs, timestamp,
- interval, n_values, src_val))) {
- for (i = 0; i < n_values; i++) {
- /* we will only get NAN for sparse control sources, such as triggers */
- if (!isnan (src_val[i])) {
- g_value_init (&values[i], type);
- convert (self, src_val[i], &values[i]);
- } else {
- GST_LOG ("no control value for property %s at index %d", _self->name,
- i);
- }
- }
- } else {
- GST_LOG ("failed to get control value for property %s at ts %"
- GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
- }
- g_free (src_val);
- return res;
-}
-
-/* functions */
-
-/**
- * gst_direct_control_binding_new:
- * @object: the object of the property
- * @property_name: the property-name to attach the control source
- * @cs: the control source
- *
- * Create a new control-binding that attaches the #GstControlSource to the
- * #GObject property. It will map the control source range [0.0 ... 1.0] to
- * the full target property range, and clip all values outside this range.
- *
- * Returns: (transfer floating): the new #GstDirectControlBinding
- */
-GstControlBinding *
-gst_direct_control_binding_new (GstObject * object, const gchar * property_name,
- GstControlSource * cs)
-{
- return (GstControlBinding *) g_object_new (GST_TYPE_DIRECT_CONTROL_BINDING,
- "object", object, "name", property_name, "control-source", cs, NULL);
-}
-
-/**
- * gst_direct_control_binding_new_absolute:
- * @object: the object of the property
- * @property_name: the property-name to attach the control source
- * @cs: the control source
- *
- * Create a new control-binding that attaches the #GstControlSource to the
- * #GObject property. It will directly map the control source values to the
- * target property range without any transformations.
- *
- * Returns: (transfer floating): the new #GstDirectControlBinding
- *
- * Since: 1.6
- */
-GstControlBinding *
-gst_direct_control_binding_new_absolute (GstObject * object,
- const gchar * property_name, GstControlSource * cs)
-{
- return (GstControlBinding *) g_object_new (GST_TYPE_DIRECT_CONTROL_BINDING,
- "object", object, "name", property_name, "control-source", cs, "absolute",
- TRUE, NULL);
-}
diff --git a/libs/gst/controller/gstdirectcontrolbinding.h b/libs/gst/controller/gstdirectcontrolbinding.h
deleted file mode 100644
index 549d1240ed..0000000000
--- a/libs/gst/controller/gstdirectcontrolbinding.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gstdirectcontrolbinding.h: Direct attachment for control sources
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_DIRECT_CONTROL_BINDING_H__
-#define __GST_DIRECT_CONTROL_BINDING_H__
-
-#include <gst/gstconfig.h>
-
-#include <glib-object.h>
-
-#include <gst/gstcontrolsource.h>
-#include <gst/controller/controller-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_DIRECT_CONTROL_BINDING \
- (gst_direct_control_binding_get_type())
-#define GST_DIRECT_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECT_CONTROL_BINDING,GstDirectControlBinding))
-#define GST_DIRECT_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECT_CONTROL_BINDING,GstDirectControlBindingClass))
-#define GST_IS_DIRECT_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECT_CONTROL_BINDING))
-#define GST_IS_DIRECT_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECT_CONTROL_BINDING))
-#define GST_DIRECT_CONTROL_BINDING_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstDirectControlBindingClass))
-
-typedef struct _GstDirectControlBinding GstDirectControlBinding;
-typedef struct _GstDirectControlBindingClass GstDirectControlBindingClass;
-
-/**
- * GstDirectControlBindingConvertValue:
- * @self: the #GstDirectControlBinding instance
- * @src_value: the value returned by the cotnrol source
- * @dest_value: the target location
- *
- * Function to map a control-value to the target plain data type.
- */
-typedef void (* GstDirectControlBindingConvertValue) (GstDirectControlBinding *self, gdouble src_value, gpointer dest_value);
-
-/**
- * GstDirectControlBindingConvertGValue:
- * @self: the #GstDirectControlBinding instance
- * @src_value: the value returned by the cotnrol source
- * @dest_value: the target GValue
- *
- * Function to map a control-value to the target GValue.
- */
-typedef void (* GstDirectControlBindingConvertGValue) (GstDirectControlBinding *self, gdouble src_value, GValue *dest_value);
-
-/**
- * GstDirectControlBinding:
- * @name: name of the property of this binding
- *
- * The instance structure of #GstDirectControlBinding.
- */
-struct _GstDirectControlBinding {
- GstControlBinding parent;
-
- /*< private >*/
- GstControlSource *cs; /* GstControlSource for this property */
- GValue cur_value;
- gdouble last_value;
- gint byte_size;
-
- GstDirectControlBindingConvertValue convert_value;
- GstDirectControlBindingConvertGValue convert_g_value;
-
- union {
- gpointer _gst_reserved[GST_PADDING];
- struct {
- gboolean want_absolute;
- } abi;
- } ABI;
-};
-
-/**
- * GstDirectControlBindingClass:
- * @parent_class: Parent class
- * @convert: Class method to convert control-values
- *
- * The class structure of #GstDirectControlBinding.
- */
-
-struct _GstDirectControlBindingClass
-{
- GstControlBindingClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_direct_control_binding_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GstControlBinding * gst_direct_control_binding_new (GstObject * object, const gchar * property_name,
- GstControlSource * cs);
-GST_CONTROLLER_API
-GstControlBinding * gst_direct_control_binding_new_absolute (GstObject * object, const gchar * property_name,
- GstControlSource * cs);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDirectControlBinding, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_DIRECT_CONTROL_BINDING_H__ */
diff --git a/libs/gst/controller/gstinterpolationcontrolsource.c b/libs/gst/controller/gstinterpolationcontrolsource.c
deleted file mode 100644
index c0b6c86c55..0000000000
--- a/libs/gst/controller/gstinterpolationcontrolsource.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * gstinterpolationcontrolsource.c: Control source that provides several
- * interpolation methods
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstinterpolationcontrolsource
- * @title: GstInterpolationControlSource
- * @short_description: interpolation control source
- *
- * #GstInterpolationControlSource is a #GstControlSource, that interpolates values between user-given
- * control points. It supports several interpolation modes and property types.
- *
- * To use #GstInterpolationControlSource get a new instance by calling
- * gst_interpolation_control_source_new(), bind it to a #GParamSpec and set some
- * control points by calling gst_timed_value_control_source_set().
- *
- * All functions are MT-safe.
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include "gstinterpolationcontrolsource.h"
-#include "gst/glib-compat-private.h"
-#include "gst/math-compat.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-/* helper functions */
-
-static inline gboolean
-_get_nearest_control_points (GstTimedValueControlSource * self,
- GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2)
-{
- GSequenceIter *iter;
-
- iter = gst_timed_value_control_source_find_control_point_iter (self, ts);
- if (iter) {
- *cp1 = g_sequence_get (iter);
- iter = g_sequence_iter_next (iter);
- if (iter && !g_sequence_iter_is_end (iter)) {
- *cp2 = g_sequence_get (iter);
- } else {
- *cp2 = NULL;
- }
- return TRUE;
- }
- return FALSE;
-}
-
-static inline void
-_get_nearest_control_points2 (GstTimedValueControlSource * self,
- GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2,
- GstClockTime * next_ts)
-{
- GSequenceIter *iter1, *iter2 = NULL;
-
- *cp1 = *cp2 = NULL;
- iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
- if (iter1) {
- *cp1 = g_sequence_get (iter1);
- iter2 = g_sequence_iter_next (iter1);
- } else {
- if (G_LIKELY (self->values)) {
- /* all values in the control point list come after the given timestamp */
- iter2 = g_sequence_get_begin_iter (self->values);
- /* why this? if !cp1 we don't interpolate anyway
- * if we can eliminate this, we can also use _get_nearest_control_points()
- * here, is this just to set next_ts? */
- } else {
- /* no values */
- iter2 = NULL;
- }
- }
-
- if (iter2 && !g_sequence_iter_is_end (iter2)) {
- *cp2 = g_sequence_get (iter2);
- *next_ts = (*cp2)->timestamp;
- } else {
- *next_ts = GST_CLOCK_TIME_NONE;
- }
-}
-
-
-/* steps-like (no-)interpolation, default */
-/* just returns the value for the most recent key-frame */
-static inline gdouble
-_interpolate_none (GstTimedValueControlSource * self, GstControlPoint * cp)
-{
- return cp->value;
-}
-
-static gboolean
-interpolate_none_get (GstTimedValueControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- gboolean ret = FALSE;
- GSequenceIter *iter;
- GstControlPoint *cp;
-
- g_mutex_lock (&self->lock);
-
- iter =
- gst_timed_value_control_source_find_control_point_iter (self, timestamp);
- if (iter) {
- cp = g_sequence_get (iter);
- *value = _interpolate_none (self, cp);
- ret = TRUE;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-static gboolean
-interpolate_none_get_value_array (GstTimedValueControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- gboolean ret = FALSE;
- guint i;
- GstClockTime ts = timestamp;
- GstClockTime next_ts = 0;
- GstControlPoint *cp1 = NULL, *cp2 = NULL;
-
- g_mutex_lock (&self->lock);
-
- for (i = 0; i < n_values; i++) {
- GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
- i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
- if (ts >= next_ts) {
- _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts);
- }
- if (cp1) {
- *values = _interpolate_none (self, cp1);
- ret = TRUE;
- GST_LOG ("values[%3d]=%lf", i, *values);
- } else {
- *values = NAN;
- GST_LOG ("values[%3d]=-", i);
- }
- ts += interval;
- values++;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-
-
-/* linear interpolation */
-/* smoothes in between values */
-static inline gdouble
-_interpolate_linear (GstClockTime timestamp1, gdouble value1,
- GstClockTime timestamp2, gdouble value2, GstClockTime timestamp)
-{
- if (GST_CLOCK_TIME_IS_VALID (timestamp2)) {
- gdouble slope;
-
- slope =
- (value2 - value1) / gst_guint64_to_gdouble (timestamp2 - timestamp1);
- return value1 + (gst_guint64_to_gdouble (timestamp - timestamp1) * slope);
- } else {
- return value1;
- }
-}
-
-static gboolean
-interpolate_linear_get (GstTimedValueControlSource * self,
- GstClockTime timestamp, gdouble * value)
-{
- gboolean ret = FALSE;
- GstControlPoint *cp1, *cp2;
-
- g_mutex_lock (&self->lock);
-
- if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) {
- *value = _interpolate_linear (cp1->timestamp, cp1->value,
- (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE),
- (cp2 ? cp2->value : 0.0), timestamp);
- ret = TRUE;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-static gboolean
-interpolate_linear_get_value_array (GstTimedValueControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- gboolean ret = FALSE;
- guint i;
- GstClockTime ts = timestamp;
- GstClockTime next_ts = 0;
- GstControlPoint *cp1 = NULL, *cp2 = NULL;
-
- g_mutex_lock (&self->lock);
-
- for (i = 0; i < n_values; i++) {
- GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
- i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
- if (ts >= next_ts) {
- _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts);
- }
- if (cp1) {
- *values = _interpolate_linear (cp1->timestamp, cp1->value,
- (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE),
- (cp2 ? cp2->value : 0.0), ts);
- ret = TRUE;
- GST_LOG ("values[%3d]=%lf", i, *values);
- } else {
- *values = NAN;
- GST_LOG ("values[%3d]=-", i);
- }
- ts += interval;
- values++;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-
-
-/* cubic interpolation */
-
-/* The following functions implement a natural cubic spline interpolator.
- * For details look at http://en.wikipedia.org/wiki/Spline_interpolation
- *
- * Instead of using a real matrix with n^2 elements for the linear system
- * of equations we use three arrays o, p, q to hold the tridiagonal matrix
- * as following to save memory:
- *
- * p[0] q[0] 0 0 0
- * o[1] p[1] q[1] 0 0
- * 0 o[2] p[2] q[2] .
- * . . . . .
- */
-
-static void
-_interpolate_cubic_update_cache (GstTimedValueControlSource * self)
-{
- gint i, n = self->nvalues;
- gdouble *o = g_new0 (gdouble, n);
- gdouble *p = g_new0 (gdouble, n);
- gdouble *q = g_new0 (gdouble, n);
-
- gdouble *h = g_new0 (gdouble, n);
- gdouble *b = g_new0 (gdouble, n);
- gdouble *z = g_new0 (gdouble, n);
-
- GSequenceIter *iter;
- GstControlPoint *cp;
- GstClockTime x, x_next;
- gdouble y_prev, y, y_next;
-
- /* Fill linear system of equations */
- iter = g_sequence_get_begin_iter (self->values);
- cp = g_sequence_get (iter);
- x = cp->timestamp;
- y = cp->value;
-
- p[0] = 1.0;
-
- iter = g_sequence_iter_next (iter);
- cp = g_sequence_get (iter);
- x_next = cp->timestamp;
- y_next = cp->value;
- h[0] = gst_guint64_to_gdouble (x_next - x);
-
- for (i = 1; i < n - 1; i++) {
- /* Shuffle x and y values */
- y_prev = y;
- x = x_next;
- y = y_next;
- iter = g_sequence_iter_next (iter);
- cp = g_sequence_get (iter);
- x_next = cp->timestamp;
- y_next = cp->value;
-
- h[i] = gst_guint64_to_gdouble (x_next - x);
- o[i] = h[i - 1];
- p[i] = 2.0 * (h[i - 1] + h[i]);
- q[i] = h[i];
- b[i] = (y_next - y) / h[i] - (y - y_prev) / h[i - 1];
- }
- p[n - 1] = 1.0;
-
- /* Use Gauss elimination to set everything below the diagonal to zero */
- for (i = 1; i < n - 1; i++) {
- gdouble a = o[i] / p[i - 1];
- p[i] -= a * q[i - 1];
- b[i] -= a * b[i - 1];
- }
-
- /* Solve everything else from bottom to top */
- for (i = n - 2; i > 0; i--)
- z[i] = (b[i] - q[i] * z[i + 1]) / p[i];
-
- /* Save cache next in the GstControlPoint */
-
- iter = g_sequence_get_begin_iter (self->values);
- for (i = 0; i < n; i++) {
- cp = g_sequence_get (iter);
- cp->cache.cubic.h = h[i];
- cp->cache.cubic.z = z[i];
- iter = g_sequence_iter_next (iter);
- }
-
- /* Free our temporary arrays */
- g_free (o);
- g_free (p);
- g_free (q);
- g_free (h);
- g_free (b);
- g_free (z);
-}
-
-static inline gdouble
-_interpolate_cubic (GstTimedValueControlSource * self, GstControlPoint * cp1,
- gdouble value1, GstControlPoint * cp2, gdouble value2,
- GstClockTime timestamp)
-{
- if (!self->valid_cache) {
- _interpolate_cubic_update_cache (self);
- self->valid_cache = TRUE;
- }
-
- if (cp2) {
- gdouble diff1, diff2;
- gdouble out;
-
- diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp);
- diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp);
-
- out =
- (cp2->cache.cubic.z * diff1 * diff1 * diff1 +
- cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h;
- out +=
- (value2 / cp1->cache.cubic.h -
- cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1;
- out +=
- (value1 / cp1->cache.cubic.h -
- cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2;
- return out;
- } else {
- return value1;
- }
-}
-
-static gboolean
-interpolate_cubic_get (GstTimedValueControlSource * self,
- GstClockTime timestamp, gdouble * value)
-{
- gboolean ret = FALSE;
- GstControlPoint *cp1, *cp2 = NULL;
-
- if (self->nvalues <= 2)
- return interpolate_linear_get (self, timestamp, value);
-
- g_mutex_lock (&self->lock);
-
- if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) {
- *value = _interpolate_cubic (self, cp1, cp1->value, cp2,
- (cp2 ? cp2->value : 0.0), timestamp);
- ret = TRUE;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-static gboolean
-interpolate_cubic_get_value_array (GstTimedValueControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- gboolean ret = FALSE;
- guint i;
- GstClockTime ts = timestamp;
- GstClockTime next_ts = 0;
- GstControlPoint *cp1 = NULL, *cp2 = NULL;
-
- if (self->nvalues <= 2)
- return interpolate_linear_get_value_array (self, timestamp, interval,
- n_values, values);
-
- g_mutex_lock (&self->lock);
-
- for (i = 0; i < n_values; i++) {
- GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
- i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
- if (ts >= next_ts) {
- _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts);
- }
- if (cp1) {
- *values = _interpolate_cubic (self, cp1, cp1->value, cp2,
- (cp2 ? cp2->value : 0.0), ts);
- ret = TRUE;
- GST_LOG ("values[%3d]=%lf", i, *values);
- } else {
- *values = NAN;
- GST_LOG ("values[%3d]=-", i);
- }
- ts += interval;
- values++;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-
-/* monotonic cubic interpolation */
-
-/* the following functions implement monotonic cubic spline interpolation.
- * For details: http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
- *
- * In contrast to the previous cubic mode, the values won't overshoot.
- */
-
-static void
-_interpolate_cubic_monotonic_update_cache (GstTimedValueControlSource * self)
-{
- gint i, n = self->nvalues;
- gdouble *dxs = g_new0 (gdouble, n);
- gdouble *dys = g_new0 (gdouble, n);
- gdouble *ms = g_new0 (gdouble, n);
- gdouble *c1s = g_new0 (gdouble, n);
-
- GSequenceIter *iter;
- GstControlPoint *cp;
- GstClockTime x, x_next, dx;
- gdouble y, y_next, dy;
-
- /* Get consecutive differences and slopes */
- iter = g_sequence_get_begin_iter (self->values);
- cp = g_sequence_get (iter);
- x_next = cp->timestamp;
- y_next = cp->value;
- for (i = 0; i < n - 1; i++) {
- x = x_next;
- y = y_next;
- iter = g_sequence_iter_next (iter);
- cp = g_sequence_get (iter);
- x_next = cp->timestamp;
- y_next = cp->value;
-
- dx = gst_guint64_to_gdouble (x_next - x);
- dy = y_next - y;
- dxs[i] = dx;
- dys[i] = dy;
- ms[i] = dy / dx;
- }
-
- /* Get degree-1 coefficients */
- c1s[0] = ms[0];
- for (i = 1; i < n; i++) {
- gdouble m = ms[i - 1];
- gdouble m_next = ms[i];
-
- if (m * m_next <= 0) {
- c1s[i] = 0.0;
- } else {
- gdouble dx_next, dx_sum;
-
- dx = dxs[i], dx_next = dxs[i + 1], dx_sum = dx + dx_next;
- c1s[i] = 3.0 * dx_sum / ((dx_sum + dx_next) / m + (dx_sum + dx) / m_next);
- }
- }
- c1s[n - 1] = ms[n - 1];
-
- /* Get degree-2 and degree-3 coefficients */
- iter = g_sequence_get_begin_iter (self->values);
- for (i = 0; i < n - 1; i++) {
- gdouble c1, m, inv_dx, common;
- cp = g_sequence_get (iter);
-
- c1 = c1s[i];
- m = ms[i];
- inv_dx = 1.0 / dxs[i];
- common = c1 + c1s[i + 1] - m - m;
-
- cp->cache.cubic_monotonic.c1s = c1;
- cp->cache.cubic_monotonic.c2s = (m - c1 - common) * inv_dx;
- cp->cache.cubic_monotonic.c3s = common * inv_dx * inv_dx;
-
- iter = g_sequence_iter_next (iter);
- }
-
- /* Free our temporary arrays */
- g_free (dxs);
- g_free (dys);
- g_free (ms);
- g_free (c1s);
-}
-
-static inline gdouble
-_interpolate_cubic_monotonic (GstTimedValueControlSource * self,
- GstControlPoint * cp1, gdouble value1, GstControlPoint * cp2,
- gdouble value2, GstClockTime timestamp)
-{
- if (!self->valid_cache) {
- _interpolate_cubic_monotonic_update_cache (self);
- self->valid_cache = TRUE;
- }
-
- if (cp2) {
- gdouble diff = gst_guint64_to_gdouble (timestamp - cp1->timestamp);
- gdouble diff2 = diff * diff;
- gdouble out;
-
- out = value1 + cp1->cache.cubic_monotonic.c1s * diff;
- out += cp1->cache.cubic_monotonic.c2s * diff2;
- out += cp1->cache.cubic_monotonic.c3s * diff * diff2;
- return out;
- } else {
- return value1;
- }
-}
-
-static gboolean
-interpolate_cubic_monotonic_get (GstTimedValueControlSource * self,
- GstClockTime timestamp, gdouble * value)
-{
- gboolean ret = FALSE;
- GstControlPoint *cp1, *cp2 = NULL;
-
- if (self->nvalues <= 2)
- return interpolate_linear_get (self, timestamp, value);
-
- g_mutex_lock (&self->lock);
-
- if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) {
- *value = _interpolate_cubic_monotonic (self, cp1, cp1->value, cp2,
- (cp2 ? cp2->value : 0.0), timestamp);
- ret = TRUE;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-static gboolean
-interpolate_cubic_monotonic_get_value_array (GstTimedValueControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- gboolean ret = FALSE;
- guint i;
- GstClockTime ts = timestamp;
- GstClockTime next_ts = 0;
- GstControlPoint *cp1 = NULL, *cp2 = NULL;
-
- if (self->nvalues <= 2)
- return interpolate_linear_get_value_array (self, timestamp, interval,
- n_values, values);
-
- g_mutex_lock (&self->lock);
-
- for (i = 0; i < n_values; i++) {
- GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
- i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
- if (ts >= next_ts) {
- _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts);
- }
- if (cp1) {
- *values = _interpolate_cubic_monotonic (self, cp1, cp1->value, cp2,
- (cp2 ? cp2->value : 0.0), ts);
- ret = TRUE;
- GST_LOG ("values[%3d]=%lf", i, *values);
- } else {
- *values = NAN;
- GST_LOG ("values[%3d]=-", i);
- }
- ts += interval;
- values++;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-
-static struct
-{
- GstControlSourceGetValue get;
- GstControlSourceGetValueArray get_value_array;
-} interpolation_modes[] = {
- {
- (GstControlSourceGetValue) interpolate_none_get,
- (GstControlSourceGetValueArray) interpolate_none_get_value_array}, {
- (GstControlSourceGetValue) interpolate_linear_get,
- (GstControlSourceGetValueArray) interpolate_linear_get_value_array}, {
- (GstControlSourceGetValue) interpolate_cubic_get,
- (GstControlSourceGetValueArray) interpolate_cubic_get_value_array}, {
- (GstControlSourceGetValue) interpolate_cubic_monotonic_get,
- (GstControlSourceGetValueArray)
-interpolate_cubic_monotonic_get_value_array}};
-
-static const guint num_interpolation_modes = G_N_ELEMENTS (interpolation_modes);
-
-enum
-{
- PROP_MODE = 1
-};
-
-struct _GstInterpolationControlSourcePrivate
-{
- GstInterpolationMode interpolation_mode;
-};
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, \
- "timeline value interpolating control source")
-
-G_DEFINE_TYPE_WITH_CODE (GstInterpolationControlSource,
- gst_interpolation_control_source, GST_TYPE_TIMED_VALUE_CONTROL_SOURCE,
- G_ADD_PRIVATE (GstInterpolationControlSource)
- _do_init);
-
-/**
- * gst_interpolation_control_source_new:
- *
- * This returns a new, unbound #GstInterpolationControlSource.
- *
- * Returns: (transfer full): a new, unbound #GstInterpolationControlSource.
- */
-GstControlSource *
-gst_interpolation_control_source_new (void)
-{
- GstControlSource *csource =
- g_object_new (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (csource);
-
- return csource;
-}
-
-static gboolean
- gst_interpolation_control_source_set_interpolation_mode
- (GstInterpolationControlSource * self, GstInterpolationMode mode)
-{
- GstControlSource *csource = GST_CONTROL_SOURCE (self);
-
- if (mode >= num_interpolation_modes || (int) mode < 0) {
- GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
- return FALSE;
- }
-
- GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
- csource->get_value = interpolation_modes[mode].get;
- csource->get_value_array = interpolation_modes[mode].get_value_array;
-
- gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
- csource);
- self->priv->interpolation_mode = mode;
-
- GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
-
- return TRUE;
-}
-
-static void
-gst_interpolation_control_source_init (GstInterpolationControlSource * self)
-{
- self->priv = gst_interpolation_control_source_get_instance_private (self);
- gst_interpolation_control_source_set_interpolation_mode (self,
- GST_INTERPOLATION_MODE_NONE);
-}
-
-static void
-gst_interpolation_control_source_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstInterpolationControlSource *self =
- GST_INTERPOLATION_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_MODE:
- gst_interpolation_control_source_set_interpolation_mode (self,
- (GstInterpolationMode) g_value_get_enum (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_interpolation_control_source_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstInterpolationControlSource *self =
- GST_INTERPOLATION_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_MODE:
- g_value_set_enum (value, self->priv->interpolation_mode);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
- * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->set_property = gst_interpolation_control_source_set_property;
- gobject_class->get_property = gst_interpolation_control_source_get_property;
-
- g_object_class_install_property (gobject_class, PROP_MODE,
- g_param_spec_enum ("mode", "Mode", "Interpolation mode",
- GST_TYPE_INTERPOLATION_MODE, GST_INTERPOLATION_MODE_NONE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
diff --git a/libs/gst/controller/gstinterpolationcontrolsource.h b/libs/gst/controller/gstinterpolationcontrolsource.h
deleted file mode 100644
index a3da267fb5..0000000000
--- a/libs/gst/controller/gstinterpolationcontrolsource.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * gstinterpolationcontrolsource.h: Control source that provides several
- * interpolation methods
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_INTERPOLATION_CONTROL_SOURCE_H__
-#define __GST_INTERPOLATION_CONTROL_SOURCE_H__
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include <gst/controller/gsttimedvaluecontrolsource.h>
-#include <gst/controller/controller-enumtypes.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_INTERPOLATION_CONTROL_SOURCE \
- (gst_interpolation_control_source_get_type ())
-#define GST_INTERPOLATION_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSource))
-#define GST_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass))
-#define GST_IS_INTERPOLATION_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE))
-#define GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE))
-#define GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS(inst) \
- (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass))
-
-typedef struct _GstInterpolationControlSource GstInterpolationControlSource;
-typedef struct _GstInterpolationControlSourceClass GstInterpolationControlSourceClass;
-typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSourcePrivate;
-
-/**
- * GstInterpolationMode:
- * @GST_INTERPOLATION_MODE_NONE: steps-like interpolation, default
- * @GST_INTERPOLATION_MODE_LINEAR: linear interpolation
- * @GST_INTERPOLATION_MODE_CUBIC: cubic interpolation (natural), may overshoot
- * the min or max values set by the control point, but is more 'curvy'
- * @GST_INTERPOLATION_MODE_CUBIC_MONOTONIC: monotonic cubic interpolation, will not
- * produce any values outside of the min-max range set by the control points
- * (Since: 1.8)
- *
- * The various interpolation modes available.
- */
-typedef enum
-{
- GST_INTERPOLATION_MODE_NONE,
- GST_INTERPOLATION_MODE_LINEAR,
- GST_INTERPOLATION_MODE_CUBIC,
- GST_INTERPOLATION_MODE_CUBIC_MONOTONIC,
-} GstInterpolationMode;
-
-/**
- * GstInterpolationControlSource:
- *
- * The instance structure of #GstControlSource.
- */
-struct _GstInterpolationControlSource {
- GstTimedValueControlSource parent;
-
- /*< private >*/
- GstInterpolationControlSourcePrivate *priv;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstInterpolationControlSourceClass {
- GstTimedValueControlSourceClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_interpolation_control_source_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GstControlSource * gst_interpolation_control_source_new (void);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstInterpolationControlSource, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_INTERPOLATION_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/gstlfocontrolsource.c b/libs/gst/controller/gstlfocontrolsource.c
deleted file mode 100644
index 1706efddfc..0000000000
--- a/libs/gst/controller/gstlfocontrolsource.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * gstlfocontrolsource.c: Control source that provides some periodic waveforms
- * as control values.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstlfocontrolsource
- * @title: GstLFOControlSource
- * @short_description: LFO control source
- *
- * #GstLFOControlSource is a #GstControlSource, that provides several periodic
- * waveforms as control values.
- *
- * To use #GstLFOControlSource get a new instance by calling
- * gst_lfo_control_source_new(), bind it to a #GParamSpec and set the relevant
- * properties.
- *
- * All functions are MT-safe.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <float.h>
-
-#include <glib-object.h>
-#include <gst/gst.h>
-#include <gst/gstcontrolsource.h>
-
-#include "gstlfocontrolsource.h"
-
-#include "gst/glib-compat-private.h"
-
-#include <gst/math-compat.h>
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-struct _GstLFOControlSourcePrivate
-{
- GstLFOWaveform waveform;
- gdouble frequency;
- GstClockTime period;
- GstClockTime timeshift;
- gdouble amplitude;
- gdouble offset;
-};
-
-/* FIXME: as % in C is not the modulo operator we need here for
- * negative numbers implement our own. Are there better ways? */
-static inline GstClockTime
-_calculate_pos (GstClockTime timestamp, GstClockTime timeshift,
- GstClockTime period)
-{
- while (timestamp < timeshift)
- timestamp += period;
-
- timestamp -= timeshift;
-
- return timestamp % period;
-}
-
-static inline gdouble
-_sine_get (GstLFOControlSource * self, gdouble amp, gdouble off,
- GstClockTime timeshift, GstClockTime period, gdouble frequency,
- GstClockTime timestamp)
-{
- gdouble pos =
- gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
- gdouble ret;
-
- ret = sin (2.0 * M_PI * (frequency / GST_SECOND) * pos);
- ret *= amp;
- ret += off;
-
- return ret;
-}
-
-static gboolean
-waveform_sine_get (GstLFOControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
-
- gst_object_sync_values (GST_OBJECT (self), timestamp);
- g_mutex_lock (&self->lock);
- *value = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, timestamp);
- g_mutex_unlock (&self->lock);
- return TRUE;
-}
-
-static gboolean
-waveform_sine_get_value_array (GstLFOControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
- guint i;
- GstClockTime ts = timestamp;
-
- for (i = 0; i < n_values; i++) {
- gst_object_sync_values (GST_OBJECT (self), ts);
- g_mutex_lock (&self->lock);
- *values = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, ts);
- g_mutex_unlock (&self->lock);
- ts += interval;
- values++;
- }
- return TRUE;
-}
-
-
-static inline gdouble
-_square_get (GstLFOControlSource * self, gdouble amp, gdouble off,
- GstClockTime timeshift, GstClockTime period, gdouble frequency,
- GstClockTime timestamp)
-{
- GstClockTime pos = _calculate_pos (timestamp, timeshift, period);
- gdouble ret;
-
- if (pos >= period / 2)
- ret = amp;
- else
- ret = -amp;
- ret += off;
-
- return ret;
-}
-
-static gboolean
-waveform_square_get (GstLFOControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
-
- gst_object_sync_values (GST_OBJECT (self), timestamp);
- g_mutex_lock (&self->lock);
- *value = _square_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, timestamp);
- g_mutex_unlock (&self->lock);
- return TRUE;
-}
-
-static gboolean
-waveform_square_get_value_array (GstLFOControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
- guint i;
- GstClockTime ts = timestamp;
-
- for (i = 0; i < n_values; i++) {
- gst_object_sync_values (GST_OBJECT (self), ts);
- g_mutex_lock (&self->lock);
- *values = _square_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, ts);
- g_mutex_unlock (&self->lock);
- ts += interval;
- values++;
- }
- return TRUE;
-}
-
-static inline gdouble
-_saw_get (GstLFOControlSource * self, gdouble amp, gdouble off,
- GstClockTime timeshift, GstClockTime period, gdouble frequency,
- GstClockTime timestamp)
-{
- gdouble pos =
- gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
- gdouble per = gst_guint64_to_gdouble (period);
- gdouble ret;
-
- ret = -((pos - per / 2.0) * ((2.0 * amp) / per));
- ret += off;
-
- return ret;
-}
-
-static gboolean
-waveform_saw_get (GstLFOControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
-
- gst_object_sync_values (GST_OBJECT (self), timestamp);
- g_mutex_lock (&self->lock);
- *value = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, timestamp);
- g_mutex_unlock (&self->lock);
- return TRUE;
-}
-
-static gboolean
-waveform_saw_get_value_array (GstLFOControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
- guint i;
- GstClockTime ts = timestamp;
-
- for (i = 0; i < n_values; i++) {
- gst_object_sync_values (GST_OBJECT (self), ts);
- g_mutex_lock (&self->lock);
- *values = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, ts);
- g_mutex_unlock (&self->lock);
- ts += interval;
- values++;
- }
- return TRUE;
-}
-
-static inline gdouble
-_rsaw_get (GstLFOControlSource * self, gdouble amp, gdouble off,
- GstClockTime timeshift, GstClockTime period, gdouble frequency,
- GstClockTime timestamp)
-{
- gdouble pos =
- gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
- gdouble per = gst_guint64_to_gdouble (period);
- gdouble ret;
-
- ret = (pos - per / 2.0) * ((2.0 * amp) / per);
- ret += off;
-
- return ret;
-}
-
-static gboolean
-waveform_rsaw_get (GstLFOControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
-
- gst_object_sync_values (GST_OBJECT (self), timestamp);
- g_mutex_lock (&self->lock);
- *value = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, timestamp);
- g_mutex_unlock (&self->lock);
- return TRUE;
-}
-
-static gboolean
-waveform_rsaw_get_value_array (GstLFOControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
- guint i;
- GstClockTime ts = timestamp;
-
- for (i = 0; i < n_values; i++) {
- gst_object_sync_values (GST_OBJECT (self), ts);
- g_mutex_lock (&self->lock);
- *values = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, ts);
- g_mutex_unlock (&self->lock);
- ts += interval;
- values++;
- }
- return TRUE;
-}
-
-
-static inline gdouble
-_triangle_get (GstLFOControlSource * self, gdouble amp, gdouble off,
- GstClockTime timeshift, GstClockTime period, gdouble frequency,
- GstClockTime timestamp)
-{
- gdouble pos =
- gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
- gdouble per = gst_guint64_to_gdouble (period);
- gdouble ret;
-
- if (pos <= 0.25 * per)
- /* 1st quarter */
- ret = pos * ((4.0 * amp) / per);
- else if (pos <= 0.75 * per)
- /* 2nd & 3rd quarter */
- ret = -(pos - per / 2.0) * ((4.0 * amp) / per);
- else
- /* 4th quarter */
- ret = -(per - pos) * ((4.0 * amp) / per);
-
- ret += off;
-
- return ret;
-}
-
-static gboolean
-waveform_triangle_get (GstLFOControlSource * self, GstClockTime timestamp,
- gdouble * value)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
-
- gst_object_sync_values (GST_OBJECT (self), timestamp);
- g_mutex_lock (&self->lock);
- *value = _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, timestamp);
- g_mutex_unlock (&self->lock);
- return TRUE;
-}
-
-static gboolean
-waveform_triangle_get_value_array (GstLFOControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- GstLFOControlSourcePrivate *priv = self->priv;
- guint i;
- GstClockTime ts = timestamp;
-
- for (i = 0; i < n_values; i++) {
- gst_object_sync_values (GST_OBJECT (self), ts);
- g_mutex_lock (&self->lock);
- *values =
- _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift,
- priv->period, priv->frequency, ts);
- g_mutex_unlock (&self->lock);
- ts += interval;
- values++;
- }
- return TRUE;
-}
-
-static struct
-{
- GstControlSourceGetValue get;
- GstControlSourceGetValueArray get_value_array;
-} waveforms[] = {
- {
- (GstControlSourceGetValue) waveform_sine_get,
- (GstControlSourceGetValueArray) waveform_sine_get_value_array}, {
- (GstControlSourceGetValue) waveform_square_get,
- (GstControlSourceGetValueArray) waveform_square_get_value_array}, {
- (GstControlSourceGetValue) waveform_saw_get,
- (GstControlSourceGetValueArray) waveform_saw_get_value_array}, {
- (GstControlSourceGetValue) waveform_rsaw_get,
- (GstControlSourceGetValueArray) waveform_rsaw_get_value_array}, {
- (GstControlSourceGetValue) waveform_triangle_get,
- (GstControlSourceGetValueArray) waveform_triangle_get_value_array}
-};
-
-static const guint num_waveforms = G_N_ELEMENTS (waveforms);
-
-enum
-{
- PROP_WAVEFORM = 1,
- PROP_FREQUENCY,
- PROP_TIMESHIFT,
- PROP_AMPLITUDE,
- PROP_OFFSET
-};
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "lfo control source", 0, "low frequency oscillator control source")
-
-#define gst_lfo_control_source_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstLFOControlSource, gst_lfo_control_source,
- GST_TYPE_CONTROL_SOURCE, G_ADD_PRIVATE (GstLFOControlSource) _do_init);
-
-static void
-gst_lfo_control_source_reset (GstLFOControlSource * self)
-{
- GstControlSource *csource = GST_CONTROL_SOURCE (self);
-
- csource->get_value = NULL;
- csource->get_value_array = NULL;
-}
-
-/**
- * gst_lfo_control_source_new:
- *
- * This returns a new, unbound #GstLFOControlSource.
- *
- * Returns: (transfer full): a new, unbound #GstLFOControlSource.
- */
-GstControlSource *
-gst_lfo_control_source_new (void)
-{
- GstControlSource *csource = g_object_new (GST_TYPE_LFO_CONTROL_SOURCE, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (csource);
-
- return csource;
-}
-
-static gboolean
-gst_lfo_control_source_set_waveform (GstLFOControlSource * self,
- GstLFOWaveform waveform)
-{
- GstControlSource *csource = GST_CONTROL_SOURCE (self);
-
- if (waveform >= num_waveforms || (int) waveform < 0) {
- GST_WARNING ("waveform %d invalid or not implemented yet", waveform);
- return FALSE;
- }
-
- csource->get_value = waveforms[waveform].get;
- csource->get_value_array = waveforms[waveform].get_value_array;
-
- self->priv->waveform = waveform;
-
- return TRUE;
-}
-
-static void
-gst_lfo_control_source_init (GstLFOControlSource * self)
-{
- self->priv = gst_lfo_control_source_get_instance_private (self);
- self->priv->waveform = gst_lfo_control_source_set_waveform (self,
- GST_LFO_WAVEFORM_SINE);
- self->priv->frequency = 1.0;
- self->priv->amplitude = 1.0;
- self->priv->period = GST_SECOND / self->priv->frequency;
- self->priv->timeshift = 0;
-
- g_mutex_init (&self->lock);
-}
-
-static void
-gst_lfo_control_source_finalize (GObject * obj)
-{
- GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (obj);
-
- gst_lfo_control_source_reset (self);
- g_mutex_clear (&self->lock);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_lfo_control_source_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_WAVEFORM:
- g_mutex_lock (&self->lock);
- gst_lfo_control_source_set_waveform (self,
- (GstLFOWaveform) g_value_get_enum (value));
- g_mutex_unlock (&self->lock);
- break;
- case PROP_FREQUENCY:{
- gdouble frequency = g_value_get_double (value);
-
- g_return_if_fail (((GstClockTime) (GST_SECOND / frequency)) != 0);
-
- g_mutex_lock (&self->lock);
- self->priv->frequency = frequency;
- self->priv->period = GST_SECOND / frequency;
- g_mutex_unlock (&self->lock);
- break;
- }
- case PROP_TIMESHIFT:
- g_mutex_lock (&self->lock);
- self->priv->timeshift = g_value_get_uint64 (value);
- g_mutex_unlock (&self->lock);
- break;
- case PROP_AMPLITUDE:
- g_mutex_lock (&self->lock);
- self->priv->amplitude = g_value_get_double (value);
- g_mutex_unlock (&self->lock);
- break;
- case PROP_OFFSET:
- g_mutex_lock (&self->lock);
- self->priv->offset = g_value_get_double (value);
- g_mutex_unlock (&self->lock);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_lfo_control_source_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_WAVEFORM:
- g_value_set_enum (value, self->priv->waveform);
- break;
- case PROP_FREQUENCY:
- g_value_set_double (value, self->priv->frequency);
- break;
- case PROP_TIMESHIFT:
- g_value_set_uint64 (value, self->priv->timeshift);
- break;
- case PROP_AMPLITUDE:
- g_value_set_double (value, self->priv->amplitude);
- break;
- case PROP_OFFSET:
- g_value_set_double (value, self->priv->offset);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = gst_lfo_control_source_finalize;
- gobject_class->set_property = gst_lfo_control_source_set_property;
- gobject_class->get_property = gst_lfo_control_source_get_property;
-
- /**
- * GstLFOControlSource:waveform:
- *
- * Specifies the waveform that should be used for this #GstLFOControlSource.
- */
- g_object_class_install_property (gobject_class, PROP_WAVEFORM,
- g_param_spec_enum ("waveform", "Waveform", "Waveform",
- GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstLFOControlSource:frequency:
- *
- * Specifies the frequency that should be used for the waveform
- * of this #GstLFOControlSource. It should be large enough
- * so that the period is longer than one nanosecond.
- */
- g_object_class_install_property (gobject_class, PROP_FREQUENCY,
- g_param_spec_double ("frequency", "Frequency",
- "Frequency of the waveform", DBL_MIN, G_MAXDOUBLE, 1.0,
- G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstLFOControlSource:timeshift:
- *
- * Specifies the timeshift to the right that should be used for the waveform
- * of this #GstLFOControlSource in nanoseconds.
- *
- * To get a n nanosecond shift to the left use
- * "(GST_SECOND / frequency) - n".
- *
- */
- g_object_class_install_property (gobject_class, PROP_TIMESHIFT,
- g_param_spec_uint64 ("timeshift", "Timeshift",
- "Timeshift of the waveform to the right", 0, G_MAXUINT64, 0,
- G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstLFOControlSource:amplitude:
- *
- * Specifies the amplitude for the waveform of this #GstLFOControlSource.
- */
- g_object_class_install_property (gobject_class, PROP_AMPLITUDE,
- g_param_spec_double ("amplitude", "Amplitude",
- "Amplitude of the waveform", 0.0, 1.0, 1.0,
- G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstLFOControlSource:offset:
- *
- * Specifies the value offset for the waveform of this #GstLFOControlSource.
- */
- g_object_class_install_property (gobject_class, PROP_OFFSET,
- g_param_spec_double ("offset", "Offset", "Offset of the waveform",
- 0.0, 1.0, 1.0,
- G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
-}
diff --git a/libs/gst/controller/gstlfocontrolsource.h b/libs/gst/controller/gstlfocontrolsource.h
deleted file mode 100644
index cc09d492c0..0000000000
--- a/libs/gst/controller/gstlfocontrolsource.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * gstlfocontrolsource.h: Control source that provides some periodic waveforms
- * as control values.
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_LFO_CONTROL_SOURCE_H__
-#define __GST_LFO_CONTROL_SOURCE_H__
-
-#include <glib-object.h>
-#include <gst/gst.h>
-#include <gst/controller/controller-enumtypes.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_LFO_CONTROL_SOURCE \
- (gst_lfo_control_source_get_type ())
-#define GST_LFO_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSource))
-#define GST_LFO_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSourceClass))
-#define GST_IS_LFO_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_LFO_CONTROL_SOURCE))
-#define GST_IS_LFO_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_LFO_CONTROL_SOURCE))
-#define GST_LFO_CONTROL_SOURCE_GET_CLASS(inst) \
- (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSourceClass))
-
-typedef struct _GstLFOControlSource GstLFOControlSource;
-typedef struct _GstLFOControlSourceClass GstLFOControlSourceClass;
-typedef struct _GstLFOControlSourcePrivate GstLFOControlSourcePrivate;
-
-/**
- * GstLFOWaveform:
- * @GST_LFO_WAVEFORM_SINE: sine waveform
- * @GST_LFO_WAVEFORM_SQUARE: square waveform
- * @GST_LFO_WAVEFORM_SAW: saw waveform
- * @GST_LFO_WAVEFORM_REVERSE_SAW: reverse saw waveform
- * @GST_LFO_WAVEFORM_TRIANGLE: triangle waveform
- *
- * The various waveform modes available.
- */
-typedef enum
-{
- GST_LFO_WAVEFORM_SINE,
- GST_LFO_WAVEFORM_SQUARE,
- GST_LFO_WAVEFORM_SAW,
- GST_LFO_WAVEFORM_REVERSE_SAW,
- GST_LFO_WAVEFORM_TRIANGLE
-} GstLFOWaveform;
-
-/**
- * GstLFOControlSource:
- *
- * The instance structure of #GstControlSource.
- */
-struct _GstLFOControlSource {
- GstControlSource parent;
-
- /* <private> */
- GstLFOControlSourcePrivate *priv;
- GMutex lock;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstLFOControlSourceClass {
- GstControlSourceClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_lfo_control_source_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GstControlSource *gst_lfo_control_source_new (void);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstLFOControlSource, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_LFO_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/gstproxycontrolbinding.c b/libs/gst/controller/gstproxycontrolbinding.c
deleted file mode 100644
index ddff085ccc..0000000000
--- a/libs/gst/controller/gstproxycontrolbinding.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2016 Matthew Waters <matthew@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstproxycontrolbinding
- * @title: GstProxyControlBinding
- * @short_description: attachment for forwarding control sources
- * @see_also: #GstControlBinding
- *
- * A #GstControlBinding that forwards requests to another #GstControlBinding
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstproxycontrolbinding.h"
-
-G_DEFINE_TYPE (GstProxyControlBinding,
- gst_proxy_control_binding, GST_TYPE_CONTROL_BINDING);
-
-static void
-gst_proxy_control_binding_init (GstProxyControlBinding * self)
-{
- g_weak_ref_init (&self->ref_object, NULL);
-}
-
-static void
-gst_proxy_control_binding_finalize (GObject * object)
-{
- GstProxyControlBinding *self = (GstProxyControlBinding *) object;
-
- g_weak_ref_clear (&self->ref_object);
- g_free (self->property_name);
-
- G_OBJECT_CLASS (gst_proxy_control_binding_parent_class)->finalize (object);
-}
-
-static gboolean
-gst_proxy_control_binding_sync_values (GstControlBinding * binding,
- GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
-{
- GstProxyControlBinding *self = (GstProxyControlBinding *)
- binding;
- gboolean ret = TRUE;
- GstObject *ref_object;
-
- ref_object = g_weak_ref_get (&self->ref_object);
- if (ref_object) {
- GstControlBinding *ref_binding =
- gst_object_get_control_binding (ref_object, self->property_name);
- if (ref_binding) {
- ret = gst_control_binding_sync_values (ref_binding, ref_object,
- timestamp, last_sync);
- gst_object_unref (ref_binding);
- }
- gst_object_unref (ref_object);
- }
-
- return ret;
-}
-
-static GValue *
-gst_proxy_control_binding_get_value (GstControlBinding * binding,
- GstClockTime timestamp)
-{
- GstProxyControlBinding *self = (GstProxyControlBinding *)
- binding;
- GValue *ret = NULL;
- GstObject *ref_object;
-
- ref_object = g_weak_ref_get (&self->ref_object);
- if (ref_object) {
- GstControlBinding *ref_binding =
- gst_object_get_control_binding (ref_object, self->property_name);
- if (ref_binding) {
- ret = gst_control_binding_get_value (ref_binding, timestamp);
- gst_object_unref (ref_binding);
- }
- gst_object_unref (ref_object);
- }
-
- return ret;
-}
-
-static gboolean
-gst_proxy_control_binding_get_value_array (GstControlBinding * binding,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gpointer values)
-{
- GstProxyControlBinding *self = (GstProxyControlBinding *)
- binding;
- gboolean ret = FALSE;
- GstObject *ref_object;
-
- ref_object = g_weak_ref_get (&self->ref_object);
- if (ref_object) {
- GstControlBinding *ref_binding =
- gst_object_get_control_binding (ref_object, self->property_name);
- if (ref_binding) {
- ret = gst_control_binding_get_value_array (ref_binding, timestamp,
- interval, n_values, values);
- gst_object_unref (ref_binding);
- }
- gst_object_unref (ref_object);
- }
-
- return ret;
-}
-
-static gboolean
-gst_proxy_control_binding_get_g_value_array (GstControlBinding *
- binding, GstClockTime timestamp, GstClockTime interval, guint n_values,
- GValue * values)
-{
- GstProxyControlBinding *self = (GstProxyControlBinding *) binding;
- gboolean ret = FALSE;
- GstObject *ref_object;
-
- ref_object = g_weak_ref_get (&self->ref_object);
- if (ref_object) {
- GstControlBinding *ref_binding =
- gst_object_get_control_binding (ref_object, self->property_name);
- if (ref_binding) {
- ret = gst_control_binding_get_g_value_array (ref_binding, timestamp,
- interval, n_values, values);
- gst_object_unref (ref_binding);
- }
- gst_object_unref (ref_object);
- }
-
- return ret;
-}
-
-static void
-gst_proxy_control_binding_class_init (GstProxyControlBindingClass * klass)
-{
- GstControlBindingClass *cb_class = GST_CONTROL_BINDING_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- cb_class->sync_values = gst_proxy_control_binding_sync_values;
- cb_class->get_value = gst_proxy_control_binding_get_value;
- cb_class->get_value_array = gst_proxy_control_binding_get_value_array;
- cb_class->get_g_value_array = gst_proxy_control_binding_get_g_value_array;
-
- gobject_class->finalize = gst_proxy_control_binding_finalize;
-}
-
-/**
- * gst_proxy_control_binding_new:
- * @object: (transfer none): a #GstObject
- * @property_name: the property name in @object to control
- * @ref_object: (transfer none): a #GstObject to forward all
- * #GstControlBinding requests to
- * @ref_property_name: the property_name in @ref_object to control
- *
- * #GstProxyControlBinding forwards all access to data or `sync_values()`
- * requests from @property_name on @object to the control binding at
- * @ref_property_name on @ref_object.
- *
- * Returns: (transfer floating): a new #GstControlBinding that proxies the control interface between
- * properties on different #GstObject's
- *
- * Since: 1.12
- */
-GstControlBinding *
-gst_proxy_control_binding_new (GstObject * object, const gchar * property_name,
- GstObject * ref_object, const gchar * ref_property_name)
-{
- GstProxyControlBinding *cb;
-
- g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
- g_return_val_if_fail (property_name != NULL, NULL);
- g_return_val_if_fail (GST_IS_OBJECT (ref_object), NULL);
- g_return_val_if_fail (ref_property_name != NULL, NULL);
-
- cb = g_object_new (GST_TYPE_PROXY_CONTROL_BINDING, "object", object,
- "name", property_name, NULL);
-
- g_weak_ref_set (&cb->ref_object, ref_object);
- cb->property_name = g_strdup (ref_property_name);
-
- return (GstControlBinding *) cb;
-}
diff --git a/libs/gst/controller/gstproxycontrolbinding.h b/libs/gst/controller/gstproxycontrolbinding.h
deleted file mode 100644
index 42e8fd9ff7..0000000000
--- a/libs/gst/controller/gstproxycontrolbinding.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2016 Matthew Waters <matthew@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_PROXY_CONTROL_BINDING_H__
-#define __GST_PROXY_CONTROL_BINDING_H__
-
-#include <gst/gst.h>
-#include <gst/controller/controller-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_PROXY_CONTROL_BINDING (gst_proxy_control_binding_get_type())
-#define GST_PROXY_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROXY_CONTROL_BINDING,GstProxyControlBinding))
-#define GST_PROXY_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROXY_CONTROL_BINDING,GstProxyControlBindingClass))
-#define GST_IS_PROXY_CONTROL_BINDING(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROXY_CONTROL_BINDING))
-#define GST_IS_PROXY_CONTROL_BINDING_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROXY_CONTROL_BINDING))
-#define GST_PROXY_CONTROL_BINDING_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstProxyControlBindingClass))
-
-typedef struct _GstProxyControlBinding GstProxyControlBinding;
-typedef struct _GstProxyControlBindingClass GstProxyControlBindingClass;
-
-/**
- * GstProxyControlBinding:
- *
- * Opaque #GstProxyControlBinding struct
- */
-struct _GstProxyControlBinding
-{
- /* <private> */
- GstControlBinding parent;
-
- GWeakRef ref_object;
- gchar *property_name;
-
- gpointer _padding[GST_PADDING];
-};
-
-/**
- * GstProxyControlBindingClass:
- *
- * Opaque #GstProxyControlBindingClass struct
- */
-struct _GstProxyControlBindingClass
-{
- /* <private> */
- GstControlBindingClass parent_class;
-
- gpointer _padding[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_proxy_control_binding_get_type (void);
-
-GST_CONTROLLER_API
-GstControlBinding * gst_proxy_control_binding_new (GstObject * object,
- const gchar * property_name,
- GstObject * ref_object,
- const gchar * ref_property_name);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstProxyControlBinding, gst_object_unref)
-G_END_DECLS
-
-#endif /* __GST_PROXY_CONTROL_BINDING_H__ */
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c
deleted file mode 100644
index 1f9c599952..0000000000
--- a/libs/gst/controller/gsttimedvaluecontrolsource.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- * 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gsttimedvaluecontrolsource.c: Base class for timeed value based control
- * sources
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gsttimedvaluecontrolsource
- * @title: GstTimedValueControlSource
- * @short_description: timed value control source base class
- *
- * Base class for #GstControlSource that use time-stamped values.
- *
- * When overriding bind, chain up first to give this bind implementation a
- * chance to setup things.
- *
- * All functions are MT-safe.
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include "gstinterpolationcontrolsource.h"
-#include "gst/glib-compat-private.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "timed value control source", 0, \
- "timed value control source base class")
-
-#define gst_timed_value_control_source_parent_class parent_class
-G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource,
- gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
-
-
-enum
-{
- VALUE_CHANGED_SIGNAL,
- VALUE_ADDED_SIGNAL,
- VALUE_REMOVED_SIGNAL,
- LAST_SIGNAL
-};
-
-static guint gst_timed_value_control_source_signals[LAST_SIGNAL] = { 0 };
-
-/**
- * gst_control_point_free:
- * @cp: the object to free
- *
- * Frees all data allocated by a #GstControlPoint instance.
- */
-void
-gst_control_point_free (GstControlPoint * cp)
-{
- g_return_if_fail (cp);
-
- g_slice_free (GstControlPoint, cp);
-}
-
-/**
- * gst_control_point_copy:
- * @cp: The control point to copy
- *
- * Copies a #GstControlPoint
- *
- * Returns: A copy of @cp
- */
-GstControlPoint *
-gst_control_point_copy (GstControlPoint * cp)
-{
- return g_slice_dup (GstControlPoint, cp);
-}
-
-GType
-gst_control_point_get_type (void)
-{
- static gsize type_id = 0;
-
- if (g_once_init_enter (&type_id)) {
- GType tmp =
- g_boxed_type_register_static (g_intern_static_string
- ("GstControlPoint"),
- (GBoxedCopyFunc) gst_control_point_copy,
- (GBoxedFreeFunc) gst_control_point_free);
- g_once_init_leave (&type_id, tmp);
- }
-
- return type_id;
-}
-
-static void
-gst_timed_value_control_source_reset (GstTimedValueControlSource * self)
-{
- GstControlSource *csource = (GstControlSource *) self;
-
- csource->get_value = NULL;
- csource->get_value_array = NULL;
-
- if (self->values) {
- g_sequence_free (self->values);
- self->values = NULL;
- }
-
- self->nvalues = 0;
- self->valid_cache = FALSE;
-}
-
-/*
- * gst_control_point_compare:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstControlPoint
- *
- * Compare function for g_list operations that operates on two #GstControlPoint
- * parameters.
- */
-static gint
-gst_control_point_compare (gconstpointer p1, gconstpointer p2)
-{
- GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
- GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
-
- return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-/*
- * gst_control_point_find:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstClockTime
- * @user_data: supplied user data
- *
- * Compare function for g_sequence operations that operates on a #GstControlPoint and
- * a #GstClockTime.
- */
-static gint
-gst_control_point_find (gconstpointer p1, gconstpointer p2, gpointer user_data)
-{
- GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
- GstClockTime ct2 = *(GstClockTime *) p2;
-
- return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-static GstControlPoint *
-_make_new_cp (GstTimedValueControlSource * self, GstClockTime timestamp,
- const gdouble value)
-{
- GstControlPoint *cp;
-
- /* create a new GstControlPoint */
- cp = g_slice_new0 (GstControlPoint);
- cp->timestamp = timestamp;
- cp->value = value;
-
- return cp;
-}
-
-static void
-gst_timed_value_control_source_set_internal (GstTimedValueControlSource *
- self, GstClockTime timestamp, const gdouble value)
-{
- GstControlPoint *cp;
-
- g_mutex_lock (&self->lock);
-
- /* check if a control point for the timestamp already exists */
- if (G_LIKELY (self->values)) {
- GSequenceIter *iter = g_sequence_lookup (self->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL);
-
- if (iter) {
- GstControlPoint *cp = g_sequence_get (iter);
-
- /* update control point */
- cp->value = value;
- g_mutex_unlock (&self->lock);
-
- g_signal_emit (self,
- gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL], 0, cp);
- goto done;
- }
- } else {
- self->values = g_sequence_new ((GDestroyNotify) gst_control_point_free);
- GST_INFO ("create new timed value sequence");
- }
-
- /* sort new cp into the prop->values list */
- cp = _make_new_cp (self, timestamp, value);
- g_sequence_insert_sorted (self->values, cp,
- (GCompareDataFunc) gst_control_point_compare, NULL);
- self->nvalues++;
- g_mutex_unlock (&self->lock);
-
- g_signal_emit (self,
- gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL], 0, cp);
-
-done:
- self->valid_cache = FALSE;
-}
-
-/**
- * gst_timed_value_control_source_find_control_point_iter:
- * @self: the control source to search in
- * @timestamp: the search key
- *
- * Find last value before given timestamp in control point list.
- * If all values in the control point list come after the given
- * timestamp or no values exist, %NULL is returned.
- *
- * For use in control source implementations.
- *
- * Returns: (transfer none): the found #GSequenceIter or %NULL
- */
-GSequenceIter *gst_timed_value_control_source_find_control_point_iter
- (GstTimedValueControlSource * self, GstClockTime timestamp)
-{
- GSequenceIter *iter;
-
- if (!self->values)
- return NULL;
-
- iter =
- g_sequence_search (self->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL);
-
- /* g_sequence_search() returns the iter where timestamp
- * would be inserted, i.e. the iter > timestamp, so
- * we need to get the previous one. And of course, if
- * there is no previous one, we return NULL. */
- if (g_sequence_iter_is_begin (iter))
- return NULL;
-
- return g_sequence_iter_prev (iter);
-}
-
-
-/**
- * gst_timed_value_control_source_set:
- * @self: the #GstTimedValueControlSource object
- * @timestamp: the time the control-change is scheduled for
- * @value: the control-value
- *
- * Set the value of given controller-handled property at a certain time.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_timed_value_control_source_set (GstTimedValueControlSource * self,
- GstClockTime timestamp, const gdouble value)
-{
- g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
- gst_timed_value_control_source_set_internal (self, timestamp, value);
-
- return TRUE;
-}
-
-/**
- * gst_timed_value_control_source_set_from_list:
- * @self: the #GstTimedValueControlSource object
- * @timedvalues: (transfer none) (element-type GstTimedValue): a list
- * with #GstTimedValue items
- *
- * Sets multiple timed values at once.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_timed_value_control_source_set_from_list (GstTimedValueControlSource *
- self, const GSList * timedvalues)
-{
- const GSList *node;
- GstTimedValue *tv;
- gboolean res = FALSE;
-
- g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
-
- for (node = timedvalues; node; node = g_slist_next (node)) {
- tv = node->data;
- if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
- GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
- GST_FUNCTION);
- } else {
- gst_timed_value_control_source_set_internal (self, tv->timestamp,
- tv->value);
- res = TRUE;
- }
- }
- return res;
-}
-
-/**
- * gst_timed_value_control_source_unset:
- * @self: the #GstTimedValueControlSource object
- * @timestamp: the time the control-change should be removed from
- *
- * Used to remove the value of given controller-handled property at a certain
- * time.
- *
- * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
- */
-gboolean
-gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
- GstClockTime timestamp)
-{
- GSequenceIter *iter;
- gboolean res = FALSE;
- GstControlPoint *cp = NULL;
-
- g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
- g_mutex_lock (&self->lock);
- /* check if a control point for the timestamp exists */
- if (G_LIKELY (self->values) && (iter =
- g_sequence_lookup (self->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL))) {
-
- /* Iter contains the iter right after timestamp, i.e.
- * we need to get the previous one and check the timestamp
- */
- cp = g_slice_dup (GstControlPoint, g_sequence_get (iter));
- g_sequence_remove (iter);
- self->nvalues--;
- self->valid_cache = FALSE;
- res = TRUE;
- }
- g_mutex_unlock (&self->lock);
-
- if (cp) {
- g_signal_emit (self,
- gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL], 0, cp);
- g_slice_free (GstControlPoint, cp);
- }
-
- return res;
-}
-
-/**
- * gst_timed_value_control_source_unset_all:
- * @self: the #GstTimedValueControlSource object
- *
- * Used to remove all time-stamped values of given controller-handled property
- *
- */
-void
-gst_timed_value_control_source_unset_all (GstTimedValueControlSource * self)
-{
- g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
-
- g_mutex_lock (&self->lock);
- /* free GstControlPoint structures */
- if (self->values) {
- g_sequence_free (self->values);
- self->values = NULL;
- }
- self->nvalues = 0;
- self->valid_cache = FALSE;
-
- g_mutex_unlock (&self->lock);
-}
-
-static void
-_append_control_point (GstControlPoint * cp, GQueue * res)
-{
- g_queue_push_tail (res, cp);
-}
-
-/**
- * gst_timed_value_control_source_get_all:
- * @self: the #GstTimedValueControlSource to get the list from
- *
- * Returns a read-only copy of the list of #GstTimedValue for the given property.
- * Free the list after done with it.
- *
- * Returns: (transfer container) (element-type GstTimedValue): a copy
- * of the list, or %NULL if the property isn't handled by the controller
- */
-GList *
-gst_timed_value_control_source_get_all (GstTimedValueControlSource * self)
-{
- GQueue res = G_QUEUE_INIT;
-
- g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), NULL);
-
- g_mutex_lock (&self->lock);
- if (G_LIKELY (self->values))
- g_sequence_foreach (self->values, (GFunc) _append_control_point, &res);
- g_mutex_unlock (&self->lock);
-
- return res.head;
-}
-
-/**
- * gst_timed_value_control_source_get_count:
- * @self: the #GstTimedValueControlSource to get the number of values from
- *
- * Get the number of control points that are set.
- *
- * Returns: the number of control points that are set.
- */
-gint
-gst_timed_value_control_source_get_count (GstTimedValueControlSource * self)
-{
- g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), 0);
- return self->nvalues;
-}
-
-/**
- * gst_timed_value_control_invalidate_cache:
- * @self: the #GstTimedValueControlSource
- *
- * Reset the controlled value cache.
- */
-void
-gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self)
-{
- g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
- self->valid_cache = FALSE;
-}
-
-static void
-gst_timed_value_control_source_init (GstTimedValueControlSource * self)
-{
- g_mutex_init (&self->lock);
-}
-
-static void
-gst_timed_value_control_source_finalize (GObject * obj)
-{
- GstTimedValueControlSource *self = GST_TIMED_VALUE_CONTROL_SOURCE (obj);
-
- g_mutex_lock (&self->lock);
- gst_timed_value_control_source_reset (self);
- g_mutex_unlock (&self->lock);
- g_mutex_clear (&self->lock);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
- * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
-
- /**
- * GstTimedValueControlSource::value-changed
- * @self: The #GstTimedValueControlSource on which a #GstTimedValue has changed
- * @timed_value: The #GstTimedValue where the value changed
- *
- * Emitted right after the new value has been set on @timed_signals
- *
- * Since: 1.6
- */
- gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL] =
- g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST, 0, NULL,
- NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
-
- /**
- * GstTimedValueControlSource::value-added
- * @self: The #GstTimedValueControlSource into which a #GstTimedValue has been
- * added
- * @timed_value: The newly added #GstTimedValue
- *
- * Emitted right after the new value has been added to @self
- *
- * Since: 1.6
- */
- gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL] =
- g_signal_new ("value-added", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST, 0, NULL,
- NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
-
- /**
- * GstTimedValueControlSource::value-removed
- * @self: The #GstTimedValueControlSource from which a #GstTimedValue has been
- * removed
- * @timed_value: The removed #GstTimedValue
- *
- * Emitted when @timed_value is removed from @self
- *
- * Since: 1.6
- */
- gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL] =
- g_signal_new ("value-removed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST, 0, NULL,
- NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
-
-
- gobject_class->finalize = gst_timed_value_control_source_finalize;
-}
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.h b/libs/gst/controller/gsttimedvaluecontrolsource.h
deleted file mode 100644
index 2baa369a23..0000000000
--- a/libs/gst/controller/gsttimedvaluecontrolsource.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gsttimedvaluecontrolsource.h: Base class for timeed value based control
- * sources
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_TIMED_VALUE_CONTROL_SOURCE_H__
-#define __GST_TIMED_VALUE_CONTROL_SOURCE_H__
-
-#include <glib-object.h>
-#include <gst/gst.h>
-#include <gst/controller/controller-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TIMED_VALUE_CONTROL_SOURCE \
- (gst_timed_value_control_source_get_type ())
-#define GST_TIMED_VALUE_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSource))
-#define GST_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
-#define GST_IS_TIMED_VALUE_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
-#define GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
-#define GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS(inst) \
- (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
-
-typedef struct _GstTimedValueControlSource GstTimedValueControlSource;
-typedef struct _GstTimedValueControlSourceClass GstTimedValueControlSourceClass;
-typedef struct _GstTimedValueControlSourcePrivate GstTimedValueControlSourcePrivate;
-typedef struct _GstControlPoint GstControlPoint;
-
-/**
- * GstControlPoint:
- * @timestamp: timestamp of the value change
- * @value: the new value
- *
- * An internal structure for value+time and various temporary
- * values used for interpolation. This "inherits" from
- * GstTimedValue.
- */
-struct _GstControlPoint
-{
- /* fields from GstTimedValue. DO NOT CHANGE! */
- GstClockTime timestamp;
- gdouble value;
-
- /*< private >*/
-
- /* Caches for the interpolators */
- /* FIXME: we should not have this here already ... */
- union {
- struct { /* 16 bytes */
- gdouble h;
- gdouble z;
- } cubic;
- struct { /* 24 bytes */
- gdouble c1s, c2s, c3s;
- } cubic_monotonic;
- guint8 _gst_reserved[64];
- } cache;
-};
-
-GST_CONTROLLER_API
-GType gst_control_point_get_type (void);
-
-/**
- * GstTimedValueControlSource:
- *
- * The instance structure of #GstControlSource.
- */
-struct _GstTimedValueControlSource {
- GstControlSource parent;
-
- /*< protected >*/
- GMutex lock;
-
- GSequence *values; /* List of GstControlPoint */
- gint nvalues; /* Number of control points */
- gboolean valid_cache;
-
- /*< private >*/
- GstTimedValueControlSourcePrivate *priv;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstTimedValueControlSourceClass {
- GstControlSourceClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-#define GST_TIMED_VALUE_CONTROL_SOURCE_LOCK(o) \
- g_mutex_lock(&((GstTimedValueControlSource *)o)->lock)
-#define GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK(o) \
- g_mutex_unlock(&((GstTimedValueControlSource *)o)->lock)
-
-GST_CONTROLLER_API
-GType gst_timed_value_control_source_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GSequenceIter * gst_timed_value_control_source_find_control_point_iter (
- GstTimedValueControlSource * self,
- GstClockTime timestamp);
-GST_CONTROLLER_API
-gboolean gst_timed_value_control_source_set (GstTimedValueControlSource * self,
- GstClockTime timestamp,
- const gdouble value);
-GST_CONTROLLER_API
-gboolean gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * self,
- const GSList * timedvalues);
-GST_CONTROLLER_API
-gboolean gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
- GstClockTime timestamp);
-
-GST_CONTROLLER_API
-void gst_timed_value_control_source_unset_all (GstTimedValueControlSource *self);
-
-GST_CONTROLLER_API
-GList * gst_timed_value_control_source_get_all (GstTimedValueControlSource * self);
-
-GST_CONTROLLER_API
-gint gst_timed_value_control_source_get_count (GstTimedValueControlSource * self);
-
-GST_CONTROLLER_API
-void gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self);
-
-GST_CONTROLLER_API
-void gst_control_point_free (GstControlPoint * cp);
-
-GST_CONTROLLER_API
-GstControlPoint * gst_control_point_copy (GstControlPoint * cp);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTimedValueControlSource, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_TIMED_VALUE_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/gsttriggercontrolsource.c b/libs/gst/controller/gsttriggercontrolsource.c
deleted file mode 100644
index 0b68cf1d5a..0000000000
--- a/libs/gst/controller/gsttriggercontrolsource.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- * 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gsttriggercontrolsource.c: Control source that provides some values at time-
- * stamps
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
- /**
- * SECTION:gsttriggercontrolsource
- * @title: GstTriggerControlSource
- * @short_description: trigger control source
- *
- * #GstTriggerControlSource is a #GstControlSource, that returns values from user-given
- * control points. It allows for a tolerance on the time-stamps.
- *
- * To use #GstTriggerControlSource get a new instance by calling
- * gst_trigger_control_source_new(), bind it to a #GParamSpec and set some
- * control points by calling gst_timed_value_control_source_set().
- *
- * All functions are MT-safe.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include "gsttriggercontrolsource.h"
-#include "gst/glib-compat-private.h"
-#include "gst/math-compat.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-struct _GstTriggerControlSourcePrivate
-{
- gint64 tolerance;
-};
-
-/* control point accessors */
-
-/* returns the default value of the property, except for times with specific values */
-/* needed for one-shot events, such as notes and triggers */
-
-static inline gdouble
-_interpolate_trigger (GstTimedValueControlSource * self, GSequenceIter * iter,
- GstClockTime timestamp)
-{
- GstControlPoint *cp;
- gint64 tolerance = ((GstTriggerControlSource *) self)->priv->tolerance;
- gboolean found = FALSE;
-
- cp = g_sequence_get (iter);
- if (GST_CLOCK_DIFF (cp->timestamp, timestamp) <= tolerance) {
- found = TRUE;
- } else {
- if ((iter = g_sequence_iter_next (iter)) && !g_sequence_iter_is_end (iter)) {
- cp = g_sequence_get (iter);
- if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) {
- found = TRUE;
- }
- }
- }
- if (found) {
- return cp->value;
- }
- return NAN;
-}
-
-static gboolean
-interpolate_trigger_get (GstTimedValueControlSource * self,
- GstClockTime timestamp, gdouble * value)
-{
- gboolean ret = FALSE;
- GSequenceIter *iter;
-
- g_mutex_lock (&self->lock);
-
- iter =
- gst_timed_value_control_source_find_control_point_iter (self, timestamp);
- if (iter) {
- *value = _interpolate_trigger (self, iter, timestamp);
- if (!isnan (*value))
- ret = TRUE;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-static gboolean
-interpolate_trigger_get_value_array (GstTimedValueControlSource * self,
- GstClockTime timestamp, GstClockTime interval, guint n_values,
- gdouble * values)
-{
- gboolean ret = FALSE;
- guint i;
- GstClockTime ts = timestamp;
- GstClockTime next_ts = 0;
- gdouble val;
- GSequenceIter *iter1 = NULL, *iter2 = NULL;
- gboolean triggered = FALSE;
-
- g_mutex_lock (&self->lock);
- for (i = 0; i < n_values; i++) {
- val = NAN;
- if (ts >= next_ts) {
- iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
- if (!iter1) {
- if (G_LIKELY (self->values))
- iter2 = g_sequence_get_begin_iter (self->values);
- else
- iter2 = NULL;
- } else {
- iter2 = g_sequence_iter_next (iter1);
- }
-
- if (iter2 && !g_sequence_iter_is_end (iter2)) {
- GstControlPoint *cp;
-
- cp = g_sequence_get (iter2);
- next_ts = cp->timestamp;
- } else {
- next_ts = GST_CLOCK_TIME_NONE;
- }
-
- if (iter1) {
- val = _interpolate_trigger (self, iter1, ts);
- if (!isnan (val))
- ret = TRUE;
- } else {
- g_mutex_unlock (&self->lock);
- return FALSE;
- }
- triggered = TRUE;
- } else if (triggered) {
- if (iter1) {
- val = _interpolate_trigger (self, iter1, ts);
- if (!isnan (val))
- ret = TRUE;
- } else {
- g_mutex_unlock (&self->lock);
- return FALSE;
- }
- triggered = FALSE;
- }
- *values = val;
- ts += interval;
- values++;
- }
- g_mutex_unlock (&self->lock);
- return ret;
-}
-
-enum
-{
- PROP_TOLERANCE = 1,
-};
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "trigger control source", 0, \
- "timeline value trigger control source")
-
-G_DEFINE_TYPE_WITH_CODE (GstTriggerControlSource, gst_trigger_control_source,
- GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, G_ADD_PRIVATE (GstTriggerControlSource)
- _do_init);
-
-/**
- * gst_trigger_control_source_new:
- *
- * This returns a new, unbound #GstTriggerControlSource.
- *
- * Returns: (transfer full): a new, unbound #GstTriggerControlSource.
- */
-GstControlSource *
-gst_trigger_control_source_new (void)
-{
- GstControlSource *csource =
- g_object_new (GST_TYPE_TRIGGER_CONTROL_SOURCE, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (csource);
-
- return csource;
-}
-
-static void
-gst_trigger_control_source_init (GstTriggerControlSource * self)
-{
- GstControlSource *csource = (GstControlSource *) self;
-
- self->priv = gst_trigger_control_source_get_instance_private (self);
-
- csource->get_value = (GstControlSourceGetValue) interpolate_trigger_get;
- csource->get_value_array = (GstControlSourceGetValueArray)
- interpolate_trigger_get_value_array;
-}
-
-static void
-gst_trigger_control_source_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_TOLERANCE:
- GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
- self->priv->tolerance = g_value_get_int64 (value);
- GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_trigger_control_source_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
-
- switch (prop_id) {
- case PROP_TOLERANCE:
- g_value_set_int64 (value, self->priv->tolerance);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_trigger_control_source_class_init (GstTriggerControlSourceClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->set_property = gst_trigger_control_source_set_property;
- gobject_class->get_property = gst_trigger_control_source_get_property;
-
- g_object_class_install_property (gobject_class, PROP_TOLERANCE,
- g_param_spec_int64 ("tolerance", "Tolerance",
- "Amount of ns a control time can be off to still trigger",
- 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-}
diff --git a/libs/gst/controller/gsttriggercontrolsource.h b/libs/gst/controller/gsttriggercontrolsource.h
deleted file mode 100644
index 431456b970..0000000000
--- a/libs/gst/controller/gsttriggercontrolsource.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 2011 Stefan Sauer <ensonic@users.sf.net>
- *
- * gsttriggercontrolsource.h: Control source that provides some values at time-
- * stamps
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_TRIGGER_CONTROL_SOURCE_H__
-#define __GST_TRIGGER_CONTROL_SOURCE_H__
-
-#include <glib-object.h>
-#include <gst/gst.h>
-
-#include <gst/controller/gsttimedvaluecontrolsource.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TRIGGER_CONTROL_SOURCE \
- (gst_trigger_control_source_get_type ())
-#define GST_TRIGGER_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSource))
-#define GST_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
-#define GST_IS_TRIGGER_CONTROL_SOURCE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE))
-#define GST_IS_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
- (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE))
-#define GST_TRIGGER_CONTROL_SOURCE_GET_CLASS(inst) \
- (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
-
-#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ())
-
-typedef struct _GstTriggerControlSource GstTriggerControlSource;
-typedef struct _GstTriggerControlSourceClass GstTriggerControlSourceClass;
-typedef struct _GstTriggerControlSourcePrivate GstTriggerControlSourcePrivate;
-
-/**
- * GstTriggerControlSource:
- *
- * The instance structure of #GstControlSource.
- */
-struct _GstTriggerControlSource {
- GstTimedValueControlSource parent;
-
- /*< private >*/
- GstTriggerControlSourcePrivate *priv;
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstTriggerControlSourceClass {
- GstTimedValueControlSourceClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_CONTROLLER_API
-GType gst_trigger_control_source_get_type (void);
-
-/* Functions */
-
-GST_CONTROLLER_API
-GstControlSource *gst_trigger_control_source_new (void);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTriggerControlSource, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_TRIGGER_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/meson.build b/libs/gst/controller/meson.build
deleted file mode 100644
index 08857cadb6..0000000000
--- a/libs/gst/controller/meson.build
+++ /dev/null
@@ -1,82 +0,0 @@
-gst_controller_sources = [
- 'gstargbcontrolbinding.c',
- 'gstdirectcontrolbinding.c',
- 'gsttimedvaluecontrolsource.c',
- 'gstinterpolationcontrolsource.c',
- 'gstproxycontrolbinding.c',
- 'gsttriggercontrolsource.c',
- 'gstlfocontrolsource.c',
-]
-
-controller_mkenum_headers = [
- 'gstinterpolationcontrolsource.h',
- 'gstlfocontrolsource.h',
-]
-
-gst_controller_headers = controller_mkenum_headers + [
- 'gstargbcontrolbinding.h',
- 'gstdirectcontrolbinding.h',
- 'gsttimedvaluecontrolsource.h',
- 'gstinterpolationcontrolsource.h',
- 'gstproxycontrolbinding.h',
- 'gsttriggercontrolsource.h',
- 'gstlfocontrolsource.h',
- 'controller-prelude.h',
- 'controller.h',
-]
-install_headers(gst_controller_headers, subdir : 'gstreamer-1.0/gst/controller/')
-
-controller_enums = gnome.mkenums_simple('controller-enumtypes',
- sources : controller_mkenum_headers,
- header_prefix : '#include <gst/controller/controller-prelude.h>',
- body_prefix : '#include "config.h"',
- decorator : 'GST_CONTROLLER_API',
- install_header : true,
- install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst/controller'))
-gstcontroller_c = controller_enums[0]
-gstcontroller_h = controller_enums[1]
-
-gst_controller_gen_sources = [gstcontroller_h]
-gst_controller = library('gstcontroller-@0@'.format(apiversion),
- gst_controller_sources, gstcontroller_h, gstcontroller_c,
- c_args : gst_c_args + ['-DBUILDING_GST_CONTROLLER'],
- install : true,
- version : libversion,
- soversion : soversion,
- darwin_versions : osxversion,
- include_directories : [configinc, libsinc],
- dependencies : [gobject_dep, glib_dep, mathlib, gst_dep],
-)
-
-pkgconfig.generate(gst_controller,
- libraries : [libgst],
- variables : pkgconfig_variables,
- subdirs : pkgconfig_subdirs,
- name : 'gstreamer-controller-1.0',
- description : 'Dynamic parameter control for GStreamer elements',
-)
-
-if build_gir
- gst_gir_extra_args = gir_init_section + [ '--c-include=gst/controller/controller.h' ]
- gst_controller_gir = gnome.generate_gir(gst_controller,
- sources : gst_controller_sources + gst_controller_headers + [gstcontroller_h] + [gstcontroller_c],
- namespace : 'GstController',
- nsversion : apiversion,
- identifier_prefix : 'Gst',
- symbol_prefix : 'gst',
- export_packages : 'gstreamer-controller-1.0',
- dependencies : [gst_dep],
- include_directories : [configinc, libsinc, privinc],
- includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
- install : true,
- extra_args : gst_gir_extra_args,
- )
- gst_controller_gen_sources += [gst_controller_gir]
-endif
-
-gst_controller_dep = declare_dependency(link_with : gst_controller,
- include_directories : [libsinc],
- sources: gst_controller_gen_sources,
- dependencies : [gst_dep])
-
-meson.override_dependency('gstreamer-controller-1.0', gst_controller_dep)
diff --git a/libs/gst/helpers/glib_gobject_helper.py b/libs/gst/helpers/glib_gobject_helper.py
deleted file mode 100644
index 5b08c386ba..0000000000
--- a/libs/gst/helpers/glib_gobject_helper.py
+++ /dev/null
@@ -1,70 +0,0 @@
-##
-## imported from glib: glib/glib_gdb.py
-##
-import gdb
-import sys
-
-if sys.version_info[0] >= 3:
- long = int
-
-# This is not quite right, as local vars may override symname
-def read_global_var (symname):
- return gdb.selected_frame().read_var(symname)
-
-def g_quark_to_string (quark):
- if quark is None:
- return None
- quark = long(quark)
- if quark == 0:
- return None
- try:
- val = read_global_var ("quarks")
- max_q = long(read_global_var ("quark_seq_id"))
- except:
- try:
- val = read_global_var ("g_quarks")
- max_q = long(read_global_var ("g_quark_seq_id"))
- except:
- return None;
- if quark < max_q:
- return val[quark].string()
- return None
-
-##
-## imported from glib: gobject/gobject_gdb.py
-##
-
-def g_type_to_typenode (gtype):
- def lookup_fundamental_type (typenode):
- if typenode == 0:
- return None
- val = read_global_var ("static_fundamental_type_nodes")
- if val is None:
- return None
- return val[typenode >> 2].address
-
- gtype = long(gtype)
- typenode = gtype - gtype % 4
- if typenode > (255 << 2):
- typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer())
- else:
- typenode = lookup_fundamental_type (typenode)
- return typenode
-
-def g_type_to_name (gtype):
- typenode = g_type_to_typenode(gtype)
- if typenode != None:
- return g_quark_to_string (typenode["qname"])
- return None
-
-def g_type_name_from_instance (instance):
- if long(instance) != 0:
- try:
- inst = instance.cast (gdb.lookup_type("GTypeInstance").pointer())
- klass = inst["g_class"]
- gtype = klass["g_type"]
- name = g_type_to_name (gtype)
- return name
- except RuntimeError:
- pass
- return None
diff --git a/libs/gst/helpers/gst-completion-helper.c b/libs/gst/helpers/gst-completion-helper.c
deleted file mode 100644
index 95821c8ab2..0000000000
--- a/libs/gst/helpers/gst-completion-helper.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* GStreamer
- * Copyright (C) 2015 Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
- *
- * gst-completion-helper.c: tool to let other tools enjoy fast and powerful
- * gstreamer-aware completion
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-
-static GList *
-get_pad_templates_info (GstElement * element, GstElementFactory * factory,
- GstPadDirection direction)
-{
- const GList *pads;
- GstStaticPadTemplate *padtemplate;
- GList *caps_list = NULL;
-
- if (gst_element_factory_get_num_pad_templates (factory) == 0) {
- g_print (" none\n");
- return NULL;
- }
-
- pads = gst_element_factory_get_static_pad_templates (factory);
- while (pads) {
- padtemplate = (GstStaticPadTemplate *) (pads->data);
- pads = g_list_next (pads);
-
- if (padtemplate->direction != direction)
- continue;
-
- if (padtemplate->static_caps.string) {
- caps_list =
- g_list_append (caps_list,
- gst_static_caps_get (&padtemplate->static_caps));
- }
-
- }
-
- return caps_list;
-}
-
-static GList *
-_get_pad_caps (const gchar * factory_name, GstPadDirection direction)
-{
- GstElementFactory *factory = gst_element_factory_find (factory_name);
- GstElement *element = gst_element_factory_make (factory_name, NULL);
-
- if (!element)
- return NULL;
- if (!factory)
- return NULL;
- factory =
- GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
- (factory)));
- if (!factory)
- return NULL;
- return get_pad_templates_info (element, factory, direction);
-}
-
-static gboolean
-_are_linkable (GstPluginFeature * feature, GList * caps_list)
-{
- gboolean print = FALSE;
- GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
-
- GList *tmp;
- print = FALSE;
- for (tmp = caps_list; tmp; tmp = tmp->next) {
- if (gst_element_factory_can_sink_any_caps (factory, tmp->data)) {
- print = TRUE;
- break;
- }
- }
-
- return print;
-}
-
-static gboolean
-_belongs_to_klass (GstElementFactory * factory, const gchar * klass)
-{
- const gchar *factory_klass;
-
-
- factory_klass =
- gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
- if (strstr (factory_klass, klass))
- return TRUE;
- return FALSE;
-}
-
-static void
-_list_features (const gchar * compatible_with, const gchar * klass,
- GstCaps * sinkcaps)
-{
- GList *plugins, *orig_plugins;
- GList *caps_list = NULL;
-
- if (compatible_with) {
- caps_list = _get_pad_caps (compatible_with, GST_PAD_SRC);
- }
-
- orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ());
- while (plugins) {
- GList *features, *orig_features;
- GstPlugin *plugin;
-
- plugin = (GstPlugin *) (plugins->data);
- plugins = g_list_next (plugins);
-
- if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) {
- continue;
- }
-
- orig_features = features =
- gst_registry_get_feature_list_by_plugin (gst_registry_get (),
- gst_plugin_get_name (plugin));
- while (features) {
- GstPluginFeature *feature;
-
- if (G_UNLIKELY (features->data == NULL))
- goto next;
- feature = GST_PLUGIN_FEATURE (features->data);
-
- if (GST_IS_ELEMENT_FACTORY (feature)) {
- gboolean print = TRUE;
- if (caps_list)
- print = _are_linkable (feature, caps_list);
- if (print && klass)
- print = _belongs_to_klass (GST_ELEMENT_FACTORY (feature), klass);
- if (print && sinkcaps)
- print =
- gst_element_factory_can_sink_any_caps (GST_ELEMENT_FACTORY
- (feature), sinkcaps);
-
- if (print)
- g_print ("%s ", gst_plugin_feature_get_name (feature));
- }
-
- next:
- features = g_list_next (features);
- }
-
- gst_plugin_feature_list_free (orig_features);
- }
-
- g_list_free (caps_list);
- g_print ("\n");
- gst_plugin_list_free (orig_plugins);
-}
-
-static void
-_print_element_properties_info (GstElement * element)
-{
- GParamSpec **property_specs;
- guint num_properties, i;
-
- property_specs = g_object_class_list_properties
- (G_OBJECT_GET_CLASS (element), &num_properties);
-
- for (i = 0; i < num_properties; i++) {
- GParamSpec *param = property_specs[i];
-
- if (param->flags & G_PARAM_WRITABLE) {
- g_print ("%s= ", g_param_spec_get_name (param));
- }
- }
-
- g_free (property_specs);
-}
-
-static void
-_list_element_properties (const gchar * factory_name)
-{
- GstElement *element = gst_element_factory_make (factory_name, NULL);
-
- _print_element_properties_info (element);
-}
-
-int
-main (int argc, char *argv[])
-{
- gboolean list_features = FALSE;
- gchar *compatible_with = NULL;
- gchar *element = NULL;
- gchar *klass = NULL;
- gchar *caps_str = NULL;
- GstCaps *sinkcaps = NULL;
- gint exit_code = EXIT_SUCCESS;
-
- GOptionEntry options[] = {
- {"list-features", 'l', 0, G_OPTION_ARG_NONE, &list_features,
- "list all the available features", NULL},
- {"compatible-with", '\0', 0, G_OPTION_ARG_STRING, &compatible_with,
- "Only print the elements that could be queued after this feature name",
- NULL},
- {"element-properties", '\0', 0, G_OPTION_ARG_STRING, &element,
- "The element to list properties on", NULL},
- {"klass", '\0', 0, G_OPTION_ARG_STRING, &klass,
- "Only print the elements belonging to that klass", NULL},
- {"sinkcaps", '\0', 0, G_OPTION_ARG_STRING, &caps_str,
- "Only print the elements that can sink these caps", NULL},
- {NULL}
- };
-
- GOptionContext *ctx;
- GError *err = NULL;
-
- ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
- g_option_context_add_main_entries (ctx, options, NULL);
- g_option_context_add_group (ctx, gst_init_get_option_group ());
- if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
- if (err)
- g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message));
- else
- g_printerr ("Error initializing: Unknown error!\n");
- g_clear_error (&err);
- g_option_context_free (ctx);
- exit (1);
- }
- g_option_context_free (ctx);
-
- if (caps_str) {
- sinkcaps = gst_caps_from_string (caps_str);
- if (!sinkcaps) {
- exit_code = EXIT_FAILURE;
- goto done;
- }
- }
-
- if (compatible_with || klass || sinkcaps) {
- _list_features (compatible_with, klass, sinkcaps);
- goto done;
- }
-
- if (element) {
- _list_element_properties (element);
- goto done;
- }
-
- if (list_features) {
- _list_features (NULL, NULL, NULL);
- goto done;
- }
-
-done:
- if (sinkcaps)
- gst_caps_unref (sinkcaps);
- exit (exit_code);
-}
diff --git a/libs/gst/helpers/gst-plugin-scanner.c b/libs/gst/helpers/gst-plugin-scanner.c
deleted file mode 100644
index cbefb29e00..0000000000
--- a/libs/gst/helpers/gst-plugin-scanner.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* GStreamer
- * Copyright (C) 2008 Jan Schmidt <jan.schmidt@sun.com>
- *
- * gst-plugin-scanner.c: tool to load plugins out of process for scanning
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Helper binary that does plugin-loading out of process and feeds results
- * back to the parent over fds.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gst/gst_private.h>
-#include <gst/gst.h>
-
-#include <string.h>
-
-int
-main (int argc, char *argv[])
-{
- gboolean res;
- char **my_argv;
- int my_argc;
-
- /* We may or may not have an executable path */
- if (argc != 2 && argc != 3)
- return 1;
-
- if (strcmp (argv[1], "-l"))
- return 1;
-
- my_argc = 2;
- my_argv = g_malloc (my_argc * sizeof (char *));
- my_argv[0] = argv[0];
- my_argv[1] = (char *) "--gst-disable-registry-update";
-
-#ifndef GST_DISABLE_REGISTRY
- _gst_disable_registry_cache = TRUE;
-#endif
-
- if (argc == 3)
- _gst_executable_path = g_strdup (argv[2]);
-
- res = gst_init_check (&my_argc, &my_argv, NULL);
-
- g_free (my_argv);
- if (!res)
- return 1;
-
- /* Create registry scanner listener and run */
- if (!_gst_plugin_loader_client_run ())
- return 1;
-
- return 0;
-}
diff --git a/libs/gst/helpers/gst-ptp-helper.c b/libs/gst/helpers/gst-ptp-helper.c
deleted file mode 100644
index 91a2570fac..0000000000
--- a/libs/gst/helpers/gst-ptp-helper.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/* GStreamer
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Helper process that runs setuid root or with appropriate privileges to
- * listen on ports < 1024, do multicast operations and get MAC addresses of
- * interfaces. Privileges are dropped after these operations are done.
- *
- * It listens on the PTP multicast group on port 319 and 320 and forwards
- * everything received there to stdout, while forwarding everything received
- * on stdout to those sockets.
- * Additionally it provides the MAC address of a network interface via stdout
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <string.h>
-
-#ifdef HAVE_GETIFADDRS_AF_LINK
-#include <ifaddrs.h>
-#include <net/if_dl.h>
-#endif
-
-#ifdef HAVE_PTP_HELPER_SETUID
-#include <grp.h>
-#include <pwd.h>
-#endif
-
-#ifdef HAVE_PTP_HELPER_CAPABILITIES
-#include <sys/capability.h>
-#endif
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include <gst/gst.h>
-#include <gst/net/gstptp_private.h>
-
-#define PTP_MULTICAST_GROUP "224.0.1.129"
-#define PTP_EVENT_PORT 319
-#define PTP_GENERAL_PORT 320
-
-static gchar **ifaces = NULL;
-static gboolean verbose = FALSE;
-static guint64 clock_id = (guint64) - 1;
-static guint8 clock_id_array[8];
-
-static GOptionEntry opt_entries[] = {
- {"interface", 'i', 0, G_OPTION_ARG_STRING_ARRAY, &ifaces,
- "Interface to listen on", NULL},
- {"clock-id", 'c', 0, G_OPTION_ARG_INT64, &clock_id,
- "PTP clock id", NULL},
- {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
- "Be verbose", NULL},
- {NULL}
-};
-
-static GSocketAddress *event_saddr, *general_saddr;
-static GSocket *socket_event, *socket_general;
-static GIOChannel *stdin_channel, *stdout_channel;
-
-static gboolean
-have_socket_data_cb (GSocket * socket, GIOCondition condition,
- gpointer user_data)
-{
- gchar buffer[8192];
- gssize read;
- gsize written;
- GError *err = NULL;
- GIOStatus status;
- StdIOHeader header = { 0, };
-
- read = g_socket_receive (socket, buffer, sizeof (buffer), NULL, &err);
- if (read == -1)
- g_error ("Failed to read from socket: %s", err->message);
- g_clear_error (&err);
-
- if (verbose)
- g_message ("Received %" G_GSSIZE_FORMAT " bytes from %s socket", read,
- (socket == socket_event ? "event" : "general"));
-
- header.size = read;
- header.type = (socket == socket_event) ? TYPE_EVENT : TYPE_GENERAL;
-
- status =
- g_io_channel_write_chars (stdout_channel, (gchar *) & header,
- sizeof (header), &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdout write status: %d", status);
- } else if (written != sizeof (header)) {
- g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- }
-
- status =
- g_io_channel_write_chars (stdout_channel, buffer, read, &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdout write status: %d", status);
- } else if (written != read) {
- g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static gboolean
-have_stdin_data_cb (GIOChannel * channel, GIOCondition condition,
- gpointer user_data)
-{
- GIOStatus status;
- StdIOHeader header = { 0, };
- gchar buffer[8192];
- GError *err = NULL;
- gsize read;
- gssize written;
-
- if ((condition & G_IO_STATUS_EOF)) {
- g_message ("EOF on stdin");
- exit (0);
- }
-
- status =
- g_io_channel_read_chars (channel, (gchar *) & header, sizeof (header),
- &read, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to read from stdin: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdin");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdin read status: %d", status);
- } else if (read != sizeof (header)) {
- g_error ("Unexpected read size: %" G_GSIZE_FORMAT, read);
- } else if (header.size > 8192) {
- g_error ("Unexpected size: %u", header.size);
- }
-
- status = g_io_channel_read_chars (channel, buffer, header.size, &read, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to read from stdin: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdin");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdin read status: %d", status);
- } else if (read != header.size) {
- g_error ("Unexpected read size: %" G_GSIZE_FORMAT, read);
- }
-
- switch (header.type) {
- case TYPE_EVENT:
- case TYPE_GENERAL:
- written =
- g_socket_send_to (header.type ==
- TYPE_EVENT ? socket_event : socket_general,
- (header.type == TYPE_EVENT ? event_saddr : general_saddr), buffer,
- header.size, NULL, &err);
- if (written == -1)
- g_error ("Failed to write to socket: %s", err->message);
- else if (written != header.size)
- g_error ("Unexpected write size: %" G_GSSIZE_FORMAT, written);
- g_clear_error (&err);
- if (verbose)
- g_message ("Sent %" G_GSSIZE_FORMAT " bytes to %s socket", read,
- (header.type == TYPE_EVENT ? "event" : "general"));
- break;
- default:
- break;
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static void
-setup_sockets (void)
-{
- GInetAddress *bind_addr, *mcast_addr;
- GSocketAddress *bind_saddr;
- GSource *socket_event_source, *socket_general_source;
- gchar **probed_ifaces = NULL;
- GError *err = NULL;
-
- /* Create sockets */
- socket_event =
- g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
- G_SOCKET_PROTOCOL_UDP, &err);
- if (!socket_event)
- g_error ("Couldn't create event socket: %s", err->message);
- g_clear_error (&err);
- g_socket_set_multicast_loopback (socket_event, FALSE);
-
- socket_general =
- g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
- G_SOCKET_PROTOCOL_UDP, &err);
- if (!socket_general)
- g_error ("Couldn't create general socket: %s", err->message);
- g_clear_error (&err);
- g_socket_set_multicast_loopback (socket_general, FALSE);
-
- /* Bind sockets */
- bind_addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
- bind_saddr = g_inet_socket_address_new (bind_addr, PTP_EVENT_PORT);
- if (!g_socket_bind (socket_event, bind_saddr, TRUE, &err))
- g_error ("Couldn't bind event socket: %s", err->message);
- g_object_unref (bind_saddr);
- bind_saddr = g_inet_socket_address_new (bind_addr, PTP_GENERAL_PORT);
- if (!g_socket_bind (socket_general, bind_saddr, TRUE, &err))
- g_error ("Couldn't bind general socket: %s", err->message);
- g_object_unref (bind_saddr);
- g_object_unref (bind_addr);
-
- /* Probe all non-loopback interfaces */
- if (!ifaces) {
-#if defined(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR)
- struct ifreq ifr;
- struct ifconf ifc;
- gchar buf[8192];
-
- ifc.ifc_len = sizeof (buf);
- ifc.ifc_buf = buf;
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) {
- guint i, idx = 0;
-
- probed_ifaces = g_new0 (gchar *, ifc.ifc_len + 1);
-
- for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) {
- strncpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name, IFNAMSIZ);
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) {
- if ((ifr.ifr_flags & IFF_LOOPBACK))
- continue;
- probed_ifaces[idx] = g_strndup (ifc.ifc_req[i].ifr_name, IFNAMSIZ);
- idx++;
- } else {
- g_warning ("can't get flags of interface '%s'",
- ifc.ifc_req[i].ifr_name);
- probed_ifaces[idx] = g_strndup (ifc.ifc_req[i].ifr_name, IFNAMSIZ);
- idx++;
- }
- if (idx != 0)
- ifaces = probed_ifaces;
- }
- }
-#elif defined(HAVE_GETIFADDRS_AF_LINK)
- struct ifaddrs *ifaddr, *ifa;
-
- if (getifaddrs (&ifaddr) != -1) {
- GPtrArray *arr;
-
- arr = g_ptr_array_new ();
-
- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
- if ((ifa->ifa_flags & IFF_LOOPBACK))
- continue;
-
- if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- g_ptr_array_add (arr, g_strdup (ifa->ifa_name));
- }
- freeifaddrs (ifaddr);
-
- g_ptr_array_add (arr, NULL);
- ifaces = probed_ifaces = (gchar **) g_ptr_array_free (arr, FALSE);
- }
-#else
-#warning "Implement something to list all network interfaces"
-#endif
- }
-
- /* Get a clock id from the MAC address if none was given */
- if (clock_id == (guint64) - 1) {
- gboolean success = FALSE;
-
-#if defined(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR)
- struct ifreq ifr;
-
- if (ifaces) {
- gchar **ptr = ifaces;
-
- while (*ptr) {
- memcpy (ifr.ifr_name, *ptr, IFNAMSIZ);
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFHWADDR, &ifr) == 0) {
- clock_id_array[0] = ifr.ifr_hwaddr.sa_data[0];
- clock_id_array[1] = ifr.ifr_hwaddr.sa_data[1];
- clock_id_array[2] = ifr.ifr_hwaddr.sa_data[2];
- clock_id_array[3] = 0xff;
- clock_id_array[4] = 0xfe;
- clock_id_array[5] = ifr.ifr_hwaddr.sa_data[3];
- clock_id_array[6] = ifr.ifr_hwaddr.sa_data[4];
- clock_id_array[7] = ifr.ifr_hwaddr.sa_data[5];
- success = TRUE;
- break;
- }
- }
-
- ptr++;
- } else {
- struct ifconf ifc;
- gchar buf[8192];
-
- ifc.ifc_len = sizeof (buf);
- ifc.ifc_buf = buf;
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) {
- guint i;
-
- for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) {
- strncpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name, IFNAMSIZ);
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) {
- if ((ifr.ifr_flags & IFF_LOOPBACK))
- continue;
-
- if (ioctl (g_socket_get_fd (socket_event), SIOCGIFHWADDR,
- &ifr) == 0) {
- clock_id_array[0] = ifr.ifr_hwaddr.sa_data[0];
- clock_id_array[1] = ifr.ifr_hwaddr.sa_data[1];
- clock_id_array[2] = ifr.ifr_hwaddr.sa_data[2];
- clock_id_array[3] = 0xff;
- clock_id_array[4] = 0xfe;
- clock_id_array[5] = ifr.ifr_hwaddr.sa_data[3];
- clock_id_array[6] = ifr.ifr_hwaddr.sa_data[4];
- clock_id_array[7] = ifr.ifr_hwaddr.sa_data[5];
- success = TRUE;
- break;
- }
- } else {
- g_warning ("can't get flags of interface '%s'",
- ifc.ifc_req[i].ifr_name);
- }
- }
- }
- }
-#elif defined(HAVE_GETIFADDRS_AF_LINK)
- struct ifaddrs *ifaddr, *ifa;
-
- if (getifaddrs (&ifaddr) != -1) {
- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
- struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
- guint8 mac_addr[6];
-
- if ((ifa->ifa_flags & IFF_LOOPBACK))
- continue;
-
- if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- if (ifaces) {
- gchar **p = ifaces;
- gboolean found = FALSE;
-
- while (*p) {
- if (strcmp (*p, ifa->ifa_name) == 0) {
- found = TRUE;
- break;
- }
- p++;
- }
-
- if (!found)
- continue;
- }
-
- if (sdl->sdl_alen != 6)
- continue;
-
- memcpy (mac_addr, LLADDR (sdl), sdl->sdl_alen);
-
- clock_id_array[0] = mac_addr[0];
- clock_id_array[1] = mac_addr[1];
- clock_id_array[2] = mac_addr[2];
- clock_id_array[3] = 0xff;
- clock_id_array[4] = 0xfe;
- clock_id_array[5] = mac_addr[3];
- clock_id_array[6] = mac_addr[4];
- clock_id_array[7] = mac_addr[5];
- success = TRUE;
- break;
- }
-
- freeifaddrs (ifaddr);
- }
-#else
-#warning "Implement something to get MAC addresses of network interfaces"
-#endif
-
- if (!success) {
- g_warning ("can't get any MAC address, using random clock id");
- clock_id = (((guint64) g_random_int ()) << 32) | (g_random_int ());
- GST_WRITE_UINT64_BE (clock_id_array, clock_id);
- clock_id_array[3] = 0xff;
- clock_id_array[4] = 0xfe;
- }
- } else {
- GST_WRITE_UINT64_BE (clock_id_array, clock_id);
- }
-
- /* Join multicast groups */
- mcast_addr = g_inet_address_new_from_string (PTP_MULTICAST_GROUP);
- if (ifaces) {
- gchar **ptr = ifaces;
- gboolean success = FALSE;
-
- while (*ptr) {
- gint c = 0;
- if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, *ptr,
- &err)
- && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
- g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr,
- err->message);
- else
- c++;
- g_clear_error (&err);
-
- if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE,
- *ptr, &err)
- && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
- g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr,
- err->message);
- else
- c++;
- g_clear_error (&err);
-
- if (c == 2)
- success = TRUE;
- ptr++;
- }
-
- if (!success) {
- /* Join multicast group without any interface */
- if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, NULL,
- &err))
- g_error ("Couldn't join multicast group: %s", err->message);
- g_clear_error (&err);
- if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE,
- NULL, &err))
- g_error ("Couldn't join multicast group: %s", err->message);
- g_clear_error (&err);
- }
- } else {
- /* Join multicast group without any interface */
- if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, NULL,
- &err))
- g_error ("Couldn't join multicast group: %s", err->message);
- g_clear_error (&err);
- if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE, NULL,
- &err))
- g_error ("Couldn't join multicast group: %s", err->message);
- g_clear_error (&err);
- }
-
- event_saddr = g_inet_socket_address_new (mcast_addr, PTP_EVENT_PORT);
- general_saddr = g_inet_socket_address_new (mcast_addr, PTP_GENERAL_PORT);
-
- /* Create socket sources */
- socket_event_source =
- g_socket_create_source (socket_event, G_IO_IN | G_IO_PRI, NULL);
- g_source_set_priority (socket_event_source, G_PRIORITY_HIGH);
- g_source_set_callback (socket_event_source, (GSourceFunc) have_socket_data_cb,
- NULL, NULL);
- g_source_attach (socket_event_source, NULL);
- socket_general_source =
- g_socket_create_source (socket_general, G_IO_IN | G_IO_PRI, NULL);
- g_source_set_priority (socket_general_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (socket_general_source,
- (GSourceFunc) have_socket_data_cb, NULL, NULL);
- g_source_attach (socket_general_source, NULL);
-
- g_strfreev (probed_ifaces);
-}
-
-static void
-drop_privileges (void)
-{
-#ifdef HAVE_PTP_HELPER_SETUID
- /* Switch to the given user/group */
-#ifdef HAVE_PTP_HELPER_SETUID_GROUP
- {
- struct group *grp;
-
- grp = getgrnam (HAVE_PTP_HELPER_SETUID_GROUP);
- if (!grp)
- g_error ("Failed to get group information '%s': %s",
- HAVE_PTP_HELPER_SETUID_GROUP, g_strerror (errno));
-
- if (setgid (grp->gr_gid) != 0)
- g_error ("Failed to change to group '%s': %s",
- HAVE_PTP_HELPER_SETUID_GROUP, g_strerror (errno));
- }
-#endif
-
-#ifdef HAVE_PTP_HELPER_SETUID_USER
- {
- struct passwd *pwd;
-
- pwd = getpwnam (HAVE_PTP_HELPER_SETUID_USER);
- if (!pwd)
- g_error ("Failed to get user information '%s': %s",
- HAVE_PTP_HELPER_SETUID_USER, g_strerror (errno));
-
-#ifndef HAVE_PTP_HELPER_SETUID_GROUP
- if (setgid (pwd->pw_gid) != 0)
- g_error ("Failed to change to user group '%s': %s",
- HAVE_PTP_HELPER_SETUID_USER, g_strerror (errno));
-#endif
-
- if (setuid (pwd->pw_uid) != 0)
- g_error ("Failed to change to user '%s': %s", HAVE_PTP_HELPER_SETUID_USER,
- g_strerror (errno));
- }
-#endif
-#endif
-#ifdef HAVE_PTP_HELPER_CAPABILITIES
- /* Drop all capabilities */
- {
- cap_t caps;
-
- caps = cap_get_proc ();
- if (caps == 0)
- g_error ("Failed to get process caps: %s", g_strerror (errno));
- if (cap_clear (caps) != 0)
- g_error ("Failed to clear caps: %s", g_strerror (errno));
- if (cap_set_proc (caps) != 0)
- g_error ("Failed to set process caps: %s", g_strerror (errno));
- }
-#endif
-}
-
-static void
-setup_stdio_channels (void)
-{
- GSource *stdin_source;
-
- /* Create stdin source */
- stdin_channel = g_io_channel_unix_new (STDIN_FILENO);
- if (g_io_channel_set_encoding (stdin_channel, NULL,
- NULL) == G_IO_STATUS_ERROR)
- g_error ("Failed to set stdin to binary encoding");
- g_io_channel_set_buffered (stdin_channel, FALSE);
- stdin_source =
- g_io_create_watch (stdin_channel, G_IO_IN | G_IO_PRI | G_IO_HUP);
- g_source_set_priority (stdin_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (stdin_source, (GSourceFunc) have_stdin_data_cb, NULL,
- NULL);
- g_source_attach (stdin_source, NULL);
-
- /* Create stdout channel */
- stdout_channel = g_io_channel_unix_new (STDOUT_FILENO);
- if (g_io_channel_set_encoding (stdout_channel, NULL,
- NULL) == G_IO_STATUS_ERROR)
- g_error ("Failed to set stdout to binary encoding");
- g_io_channel_set_buffered (stdout_channel, FALSE);
-}
-
-static void
-write_clock_id (void)
-{
- GError *err = NULL;
- GIOStatus status;
- StdIOHeader header = { 0, };
- gsize written;
-
- /* Write clock id to stdout */
-
- header.type = TYPE_CLOCK_ID;
- header.size = 8;
- status =
- g_io_channel_write_chars (stdout_channel, (gchar *) & header,
- sizeof (header), &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdout write status: %d", status);
- } else if (written != sizeof (header)) {
- g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- }
-
- status =
- g_io_channel_write_chars (stdout_channel,
- (const gchar *) clock_id_array, sizeof (clock_id_array), &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_error ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- exit (0);
- } else if (status != G_IO_STATUS_NORMAL) {
- g_error ("Unexpected stdout write status: %d", status);
- } else if (written != sizeof (clock_id_array)) {
- g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- }
-}
-
-#ifdef __APPLE__
-static gint
-dummy_poll (GPollFD * fds, guint nfds, gint timeout)
-{
- return g_poll (fds, nfds, timeout);
-}
-#endif
-
-gint
-main (gint argc, gchar ** argv)
-{
- GOptionContext *opt_ctx;
- GMainLoop *loop;
- GError *err = NULL;
-
- /* FIXME: Work around some side effects of the changes from
- * https://bugzilla.gnome.org/show_bug.cgi?id=741054
- *
- * The modified poll function somehow calls setugid(), which
- * then abort()s the application. Make sure that we use g_poll()
- * here!
- */
-#ifdef __APPLE__
- {
- GMainContext *context = g_main_context_default ();
- g_main_context_set_poll_func (context, dummy_poll);
- }
-#endif
-
-#ifdef HAVE_PTP_HELPER_SETUID
- if (setuid (0) < 0)
- g_error ("not running with superuser privileges");
-#endif
-
- opt_ctx = g_option_context_new ("- GStreamer PTP helper process");
- g_option_context_add_main_entries (opt_ctx, opt_entries, NULL);
- if (!g_option_context_parse (opt_ctx, &argc, &argv, &err))
- g_error ("Error parsing options: %s", err->message);
- g_clear_error (&err);
- g_option_context_free (opt_ctx);
-
- setup_sockets ();
- drop_privileges ();
- setup_stdio_channels ();
- write_clock_id ();
-
- /* Get running */
- loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (loop);
-
- /* We never exit cleanly, so don't do cleanup */
- g_assert_not_reached ();
-
- return 0;
-}
diff --git a/libs/gst/helpers/gst_gdb.py b/libs/gst/helpers/gst_gdb.py
deleted file mode 100644
index 90374fba97..0000000000
--- a/libs/gst/helpers/gst_gdb.py
+++ /dev/null
@@ -1,1277 +0,0 @@
-# GStreamer
-# Copyright (C) 2018 Pengutronix, Michael Olbrich <m.olbrich@pengutronix.de>
-#
-# gst_gdb.py: gdb extension for GStreamer
-#
-# 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., 51 Franklin St, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-
-import gdb
-import sys
-import re
-
-from glib_gobject_helper import g_type_to_name, g_type_name_from_instance, \
- g_type_to_typenode, g_quark_to_string
-
-if sys.version_info[0] >= 3:
- long = int
-
-
-def is_gst_type(val, klass):
- def _is_gst_type(type):
- if str(type) == klass:
- return True
-
- while type.code == gdb.TYPE_CODE_TYPEDEF:
- type = type.target()
-
- if type.code != gdb.TYPE_CODE_STRUCT:
- return False
-
- fields = type.fields()
- if len(fields) < 1:
- return False
-
- first_field = fields[0]
- return _is_gst_type(first_field.type)
-
- type = val.type
- if type.code != gdb.TYPE_CODE_PTR:
- return False
- type = type.target()
- return _is_gst_type(type)
-
-
-class GstMiniObjectPrettyPrinter:
- "Prints a GstMiniObject instance pointer"
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- try:
- inst = self.val.cast(gdb.lookup_type("GstMiniObject").pointer())
- gtype = inst["type"]
- name = g_type_to_name(gtype)
- return "0x%x [%s]" % (long(self.val), name)
- except RuntimeError:
- return "0x%x" % long(self.val)
-
-
-class GstObjectPrettyPrinter:
- "Prints a GstObject instance"
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- try:
- name = g_type_name_from_instance(self.val)
- if not name:
- name = str(self.val.type.target())
- if long(self.val) != 0:
- inst = self.val.cast(gdb.lookup_type("GstObject").pointer())
- inst_name = inst["name"].string()
- if inst_name:
- name += "|" + inst_name
- return ("0x%x [%s]") % (long(self.val), name)
- except RuntimeError:
- return "0x%x" % long(self.val)
-
-
-GST_SECOND = 1000000000
-GST_CLOCK_TIME_NONE = 2**64-1
-GST_CLOCK_STIME_NONE = -2**63
-
-
-def format_time(n, signed=False):
- prefix = ""
- invalid = False
- if signed:
- if n == GST_CLOCK_STIME_NONE:
- invalid = True
- prefix = "+" if n >= 0 else "-"
- n = abs(n)
- else:
- if n == GST_CLOCK_TIME_NONE:
- invalid = True
-
- if invalid:
- return "99:99:99.999999999"
-
- return "%s%u:%02u:%02u.%09u" % (
- prefix,
- n / (GST_SECOND * 60 * 60),
- (n / (GST_SECOND * 60)) % 60,
- (n / GST_SECOND) % 60,
- n % GST_SECOND)
-
-
-def format_time_value(val):
- return format_time(int(val), str(val.type) == "GstClockTimeDiff")
-
-
-class GstClockTimePrinter:
- "Prints a GstClockTime / GstClockTimeDiff"
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return "%d [%s]" % (int(self.val), format_time_value(self.val))
-
-
-def gst_pretty_printer_lookup(val):
- if is_gst_type(val, "GstMiniObject"):
- return GstMiniObjectPrettyPrinter(val)
- if is_gst_type(val, "GstObject"):
- return GstObjectPrettyPrinter(val)
- if str(val.type) == "GstClockTime" or str(val.type) == "GstClockTimeDiff":
- return GstClockTimePrinter(val)
- return None
-
-
-def save_memory_access(fallback):
- def _save_memory_access(func):
- def wrapper(*args, **kwargs):
- try:
- return func(*args, **kwargs)
- except gdb.MemoryError:
- return fallback
- return wrapper
- return _save_memory_access
-
-
-def save_memory_access_print(message):
- def _save_memory_access_print(func):
- def wrapper(*args, **kwargs):
- try:
- func(*args, **kwargs)
- except gdb.MemoryError:
- _gdb_write(args[1], message)
- return wrapper
- return _save_memory_access_print
-
-
-def _g_type_from_instance(instance):
- if long(instance) != 0:
- try:
- inst = instance.cast(gdb.lookup_type("GTypeInstance").pointer())
- klass = inst["g_class"]
- gtype = klass["g_type"]
- return gtype
- except RuntimeError:
- pass
- return None
-
-
-def g_inherits_type(val, typename):
- if is_gst_type(val, "GstObject"):
- gtype = _g_type_from_instance(val)
- if gtype is None:
- return False
- typenode = g_type_to_typenode(gtype)
- elif is_gst_type(val, "GstMiniObject"):
- mini = val.cast(gdb.lookup_type("GstMiniObject").pointer())
- try:
- typenode = mini["type"].cast(gdb.lookup_type("TypeNode").pointer())
- except gdb.MemoryError:
- return False
- else:
- return False
-
- for i in range(typenode["n_supers"]):
- if g_type_to_name(typenode["supers"][i]) == typename:
- return True
- return False
-
-
-def gst_is_bin(val):
- return g_inherits_type(val, "GstBin")
-
-
-def _g_array_iter(array, element_type):
- if array == 0:
- return
- try:
- item = array["data"].cast(element_type.pointer())
- for i in range(int(array["len"])):
- yield item[i]
- except gdb.MemoryError:
- pass
-
-
-def _g_value_get_value(val):
- typenode = g_type_to_typenode(val["g_type"])
- if not typenode:
- return None
- tname = g_quark_to_string(typenode["qname"])
- fname = g_type_to_name(typenode["supers"][int(typenode["n_supers"])])
- if fname in ("gchar", "guchar", "gboolean", "gint", "guint", "glong",
- "gulong", "gint64", "guint64", "gfloat", "gdouble",
- "gpointer", "GFlags"):
- try:
- t = gdb.lookup_type(tname).pointer()
- except RuntimeError:
- t = gdb.lookup_type(fname).pointer()
- elif fname == "gchararray":
- t = gdb.lookup_type("char").pointer().pointer()
- elif fname == "GstBitmask":
- t = gdb.lookup_type("guint64").pointer()
- elif fname == "GstFlagSet":
- t = gdb.lookup_type("guint").pointer().pointer()
- return val["data"].cast(t)
- elif fname == "GstFraction":
- t = gdb.lookup_type("gint").pointer().pointer()
- return val["data"].cast(t)
- elif fname == "GstFractionRange":
- t = gdb.lookup_type("GValue").pointer().pointer()
- elif fname == "GstValueList":
- t = gdb.lookup_type("GArray").pointer().pointer()
- elif fname in ("GBoxed", "GObject"):
- try:
- t = gdb.lookup_type(tname).pointer().pointer()
- except RuntimeError:
- t = gdb.lookup_type(tname).pointer().pointer()
- else:
- return val["data"]
-
- return val["data"].cast(t).dereference()
-
-
-def gst_object_from_value(value):
- if value.type.code != gdb.TYPE_CODE_PTR:
- value = value.address
-
- if not is_gst_type(value, "GstObject"):
- raise Exception("'%s' is not a GstObject" % args[0])
-
- return value.cast(gdb.lookup_type("GstObject").pointer())
-
-
-def gst_object_pipeline(obj):
- try:
- while obj["parent"] != 0:
- tmp = obj["parent"]
- # sanity checks to handle memory corruption
- if g_inherits_type(obj, "GstElement") and \
- GdbGstElement(obj) not in GdbGstElement(tmp).children():
- break
- if g_inherits_type(obj, "GstPad"):
- pad = GdbGstPad(obj)
- if g_inherits_type(tmp, "GstElement"):
- if pad not in GdbGstElement(tmp).pads():
- break
- elif g_inherits_type(tmp, "GstProxyPad"):
- t = gdb.lookup_type("GstProxyPad").pointer()
- if pad != GdbGstPad(tmp.cast(t)["priv"]["internal"]):
- break
- obj = tmp
- except gdb.MemoryError:
- pass
-
- if not g_inherits_type(obj, "GstElement"):
- raise Exception("Toplevel parent is not a GstElement")
- return obj.cast(gdb.lookup_type("GstElement").pointer())
-
-
-def element_state_to_name(state):
- names = [
- "VOID_PENDING",
- "NULL",
- "READY",
- "PAUSED",
- "PLAYING"]
- return names[state] if state < len(names) else "UNKNOWN"
-
-
-def task_state_to_name(state):
- names = [
- "STARTED",
- "STOPPED",
- "PAUSED"]
- return names[state] if state < len(names) else "UNKNOWN"
-
-
-def _gdb_write(indent, text):
- gdb.write("%s%s\n" % (" " * indent, text))
-
-
-class GdbCapsFeatures:
- def __init__(self, val):
- self.val = val
-
- def size(self):
- if long(self.val) == 0:
- return 0
- return int(self.val["array"]["len"])
-
- def items(self):
- if long(self.val) == 0:
- return
- for q in _g_array_iter(self.val["array"], gdb.lookup_type("GQuark")):
- yield q
-
- def __eq__(self, other):
- if self.size() != other.size():
- return False
- a1 = list(self.items())
- a2 = list(other.items())
- for item in a1:
- if item not in a2:
- return False
- return True
-
- def __str__(self):
- if long(self.val) == 0:
- return ""
- count = self.size()
- if int(self.val["is_any"]) == 1 and count == 0:
- return "(ANY)"
- if count == 0:
- return ""
- s = ""
- for f in self.items():
- ss = g_quark_to_string(f)
- if ss != "memory:SystemMemory" or count > 1:
- s += ", " if s else ""
- s += ss
- return s
-
-
-class GdbGstCaps:
- def __init__(self, val):
- self.val = val.cast(gdb.lookup_type("GstCapsImpl").pointer())
-
- def size(self):
- return int(self.val["array"]["len"])
-
- def items(self):
- gdb_type = gdb.lookup_type("GstCapsArrayElement")
- for f in _g_array_iter(self.val["array"], gdb_type):
- yield(GdbCapsFeatures(f["features"]),
- GdbGstStructure(f["structure"]))
-
- def __eq__(self, other):
- if self.size() != other.size():
- return False
- a1 = list(self.items())
- a2 = list(other.items())
- for i in range(self.size()):
- if a1[i] != a2[i]:
- return False
- return True
-
- def dot(self):
- if self.size() == 0:
- return "ANY"
- s = ""
- for (features, structure) in self.items():
- s += structure.name()
- tmp = str(features)
- if tmp:
- s += "(" + tmp + ")"
- s += "\\l"
- if structure.size() > 0:
- s += "\\l".join(structure.value_strings(" %18s: %s")) + "\\l"
- return s
-
- @save_memory_access_print("<inaccessible memory>")
- def print(self, indent, prefix=""):
- items = list(self.items())
- if len(items) != 1:
- _gdb_write(indent, prefix)
- prefix = ""
- for (features, structure) in items:
- s = "%s %s" % (prefix, structure.name())
- tmp = str(features)
- if tmp:
- s += "(" + tmp + ")"
- _gdb_write(indent, s)
- for val in structure.value_strings("%s: %s", False):
- _gdb_write(indent+1, val)
- return s
-
-
-class GdbGValue:
- def __init__(self, val):
- self.val = val
-
- def fundamental_typename(self):
- typenode = g_type_to_typenode(self.val["g_type"])
- if not typenode:
- return None
- return g_type_to_name(typenode["supers"][int(typenode["n_supers"])])
-
- def value(self):
- return _g_value_get_value(self.val)
-
- def __str__(self):
- try:
- value = self.value()
- tname = self.fundamental_typename()
- gvalue_type = gdb.lookup_type("GValue")
- if tname == "GstFraction":
- v = "%d/%d" % (value[0], value[1])
- elif tname == "GstBitmask":
- v = "0x%016x" % long(value)
- elif tname == "gboolean":
- v = "false" if int(value) == 0 else "true"
- elif tname == "GstFlagSet":
- v = "%x:%x" % (value[0], value[1])
- elif tname == "GstIntRange":
- rmin = int(value[0]["v_uint64"]) >> 32
- rmax = int(value[0]["v_uint64"]) & 0xffffffff
- step = int(value[1]["v_int"])
- if step == 1:
- v = "[ %d, %d ]" % (rmin, rmax)
- else:
- v = "[ %d, %d, %d ]" % (rmin*step, rmax*step, step)
- elif tname == "GstFractionRange":
- v = "[ %s, %s ]" % (GdbGValue(value[0]), GdbGValue(value[1]))
- elif tname in ("GstValueList", "GstValueArray"):
- if gvalue_type.fields()[1].type == value.type:
- gdb_type = gdb.lookup_type("GArray").pointer()
- value = value[0]["v_pointer"].cast(gdb_type)
- v = "<"
- for l in _g_array_iter(value, gvalue_type):
- v += " " if v == "<" else ", "
- v += str(GdbGValue(l))
- v += " >"
- elif tname in ("GEnum"):
- v = "%s(%s)" % (
- g_type_to_name(g_type_to_typenode(self.val["g_type"])),
- value["v_int"])
- else:
- try:
- v = value.string()
- except RuntimeError:
- # it is not a string-like type
- if gvalue_type.fields()[1].type == value.type:
- # don't print the raw GValue union
- v = "<unknown type: %s>" % tname
- else:
- v = str(value)
- except gdb.MemoryError:
- v = "<inaccessible memory at 0x%x>" % int(self.val)
- return v
-
- def __eq__(self, other):
- return self.val == other.val
-
-
-class GdbGstStructure:
- def __init__(self, val):
- self.val = val.cast(gdb.lookup_type("GstStructureImpl").pointer())
-
- @save_memory_access("<inaccessible memory>")
- def name(self):
- return g_quark_to_string(self.val["s"]["name"])
-
- @save_memory_access(0)
- def size(self):
- return int(self.val["fields_len"])
-
- def values(self):
- item = self.val["fields"].cast(gdb.lookup_type("GstStructureField").pointer())
- for i in range(self.size()):
- f = item[i]
- key = g_quark_to_string(f["name"])
- value = GdbGValue(f["value"])
- yield(key, value)
-
- def value(self, key):
- for (k, value) in self.values():
- if k == key:
- return value
- raise KeyError(key)
-
- def __eq__(self, other):
- if self.size() != other.size():
- return False
- a1 = list(self.values())
- a2 = list(other.values())
- for (key, value) in a1:
- if (key, value) not in a2:
- return False
- return True
-
- def value_strings(self, pattern, elide=True):
- s = []
- for (key, value) in self.values():
- v = str(value)
- if elide and len(v) > 25:
- if v[0] in "[(<\"":
- v = v[:20] + "... " + v[-1:]
- else:
- v = v[:22] + "..."
- s.append(pattern % (key, v))
- return s
-
- @save_memory_access_print("<inaccessible memory>")
- def print(self, indent, prefix=None):
- if prefix is not None:
- _gdb_write(indent, "%s: %s" % (prefix, self.name()))
- else:
- _gdb_write(indent, "%s:" % (self.name()))
- for (key, value) in self.values():
- _gdb_write(indent+1, "%s: %s" % (key, str(value)))
-
-
-class GdbGstSegment:
- def __init__(self, val):
- self.val = val
- self.fmt = str(self.val["format"]).split("_")[-1].lower()
-
- def format_value(self, n):
- if self.fmt == "time":
- return format_time(n, False)
- else:
- return str(n)
-
- def print_optional(self, indent, key, skip=None):
- value = int(self.val[key])
- if skip is None or value != skip:
- _gdb_write(indent, "%s:%s %s" %
- (key, (8-len(key))*" ", self.format_value(value)))
-
- def print(self, indent, seqnum=None):
- s = "segment:"
- if seqnum:
- s += "(seqnum: %s)" % seqnum
- _gdb_write(indent, s)
- rate = float(self.val["rate"])
- applied_rate = float(self.val["applied_rate"])
- if applied_rate != 1.0:
- applied = "(applied rate: %g)" % applied_rate
- else:
- applied = ""
- _gdb_write(indent+1, "rate: %g%s" % (rate, applied))
- self.print_optional(indent+1, "base", 0)
- self.print_optional(indent+1, "offset", 0)
- self.print_optional(indent+1, "start")
- self.print_optional(indent+1, "stop", GST_CLOCK_TIME_NONE)
- self.print_optional(indent+1, "time")
- self.print_optional(indent+1, "position")
- self.print_optional(indent+1, "duration", GST_CLOCK_TIME_NONE)
-
-
-class GdbGstEvent:
- def __init__(self, val):
- self.val = val.cast(gdb.lookup_type("GstEventImpl").pointer())
-
- @save_memory_access("<inaccessible memory>")
- def typestr(self):
- t = self.val["event"]["type"]
- (event_quarks, _) = gdb.lookup_symbol("event_quarks")
- event_quarks = event_quarks.value()
- i = 0
- while event_quarks[i]["name"] != 0:
- if t == event_quarks[i]["type"]:
- return event_quarks[i]["name"].string()
- i += 1
- return None
-
- def structure(self):
- return GdbGstStructure(self.val["structure"])
-
- @save_memory_access_print("<inaccessible memory>")
- def print(self, indent):
- typestr = self.typestr()
- seqnum = self.val["event"]["seqnum"]
- if typestr == "caps":
- caps = GdbGstCaps(self.structure().value("caps").value())
- caps.print(indent, "caps (seqnum: %s):" % seqnum)
- elif typestr == "stream-start":
- stream_id = self.structure().value("stream-id").value()
- _gdb_write(indent, "stream-start: (seqnum %s)" % seqnum)
- _gdb_write(indent + 1, "stream-id: %s" % stream_id.string())
- elif typestr == "segment":
- segment = self.structure().value("segment").value()
- GdbGstSegment(segment).print(indent, seqnum)
- elif typestr == "tag":
- struct = self.structure()
- # skip 'GstTagList-'
- name = struct.name()[11:]
- t = gdb.lookup_type("GstTagListImpl").pointer()
- s = struct.value("taglist").value().cast(t)["structure"]
- structure = GdbGstStructure(s)
- _gdb_write(indent, "tag: %s (seqnum: %s)" % (name, seqnum))
- for (key, value) in structure.values():
- _gdb_write(indent+1, "%s: %s" % (key, str(value)))
- else:
- self.structure().print(indent, "%s (seqnum: %s)" % (typestr, seqnum))
-
-
-class GdbGstBuffer:
- def __init__(self, val):
- self.val = val.cast(gdb.lookup_type("GstBuffer").pointer())
-
- def print_optional(self, indent, key, skip=None, format_func=str):
- value = int(self.val[key])
- if skip is None or value != skip:
- _gdb_write(indent, "%s:%s %s" %
- (key, (8-len(key))*" ", format_func(value)))
-
- @save_memory_access_print("<inaccessible memory>")
- def print(self, indent):
- _gdb_write(indent, "GstBuffer: (0x%x)" % self.val)
- indent += 1
- self.print_optional(indent, "pool", 0)
- self.print_optional(indent, "pts", GST_CLOCK_TIME_NONE, format_time)
- self.print_optional(indent, "dts", GST_CLOCK_TIME_NONE, format_time)
- self.print_optional(indent, "duration", GST_CLOCK_TIME_NONE, format_time)
- self.print_optional(indent, "offset", GST_CLOCK_TIME_NONE)
- self.print_optional(indent, "offset_end", GST_CLOCK_TIME_NONE)
-
- impl = self.val.cast(gdb.lookup_type("GstBufferImpl").pointer())
- meta_item = impl['item']
- if meta_item:
- _gdb_write(indent, "Metas:")
- indent += 1
- while meta_item:
- meta = meta_item['meta']
- meta_type_name = g_type_to_name(meta['info']['type'])
- _gdb_write(indent, "%s:" % meta_type_name)
- indent += 1
- meta_info = str(meta.cast(gdb.lookup_type(meta_type_name)))
- for l in meta_info.split('\n'):
- _gdb_write(indent, l)
- indent -= 1
- meta_item = meta_item['next']
- else:
- _gdb_write(indent, "(No meta)")
-
-
-class GdbGstQuery:
- def __init__(self, val):
- self.val = val.cast(gdb.lookup_type("GstQueryImpl").pointer())
-
- @save_memory_access("<inaccessible memory>")
- def typestr(self):
- t = self.val["query"]["type"]
- (query_quarks, _) = gdb.lookup_symbol("query_quarks")
- query_quarks = query_quarks.value()
- i = 0
- while query_quarks[i]["name"] != 0:
- if t == query_quarks[i]["type"]:
- return query_quarks[i]["name"].string()
- i += 1
- return None
-
- def structure(self):
- return GdbGstStructure(self.val["structure"])
-
- @save_memory_access_print("<inaccessible memory>")
- def print(self, indent):
- typestr = self.typestr()
- self.structure().print(indent, typestr)
-
-
-class GdbGstObject:
- def __init__(self, klass, val):
- self.val = val.cast(klass)
-
- @save_memory_access("<inaccessible memory>")
- def name(self):
- obj = self.val.cast(gdb.lookup_type("GstObject").pointer())
- return obj["name"].string()
-
- def full_name(self):
- parent = self.parent_element()
- return "%s%s" % (parent.name() + ":" if parent else "", self.name())
-
- def dot_name(self):
- ptr = self.val.cast(gdb.lookup_type("void").pointer())
- return re.sub('[^a-zA-Z0-9<>]', '_', "%s_%s" % (self.name(), str(ptr)))
-
- def parent(self):
- obj = self.val.cast(gdb.lookup_type("GstObject").pointer())
- return obj["parent"]
-
- def parent_element(self):
- p = self.parent()
- if p != 0 and g_inherits_type(p, "GstElement"):
- element = p.cast(gdb.lookup_type("GstElement").pointer())
- return GdbGstElement(element)
- return None
-
- def parent_pad(self):
- p = self.parent()
- if p != 0 and g_inherits_type(p, "GstPad"):
- pad = p.cast(gdb.lookup_type("GstPad").pointer())
- return GdbGstPad(pad)
- return None
-
-
-class GdbGstPad(GdbGstObject):
- def __init__(self, val):
- gdb_type = gdb.lookup_type("GstPad").pointer()
- super(GdbGstPad, self).__init__(gdb_type, val)
-
- def __eq__(self, other):
- return self.val == other.val
-
- def is_linked(self):
- return long(self.val["peer"]) != 0
-
- def peer(self):
- return GdbGstPad(self.val["peer"])
-
- def direction(self):
- return str(self.val["direction"])
-
- def events(self):
- if long(self.val["priv"]) == 0:
- return
- array = self.val["priv"]["events"]
- for ev in _g_array_iter(array, gdb.lookup_type("PadEvent")):
- yield GdbGstEvent(ev["event"])
-
- def caps(self):
- for ev in self.events():
- if ev.typestr() != "caps":
- continue
- return GdbGstCaps(ev.structure().value("caps").value())
- return None
-
- def template_caps(self):
- tmp = self.val["padtemplate"]
- return GdbGstCaps(tmp["caps"]) if int(tmp) != 0 else None
-
- def mode(self):
- m = str(self.val["mode"]).split("_")[-1].lower()
- if m in ("push", "pull"):
- return m
- return None
-
- def pad_type(self):
- s = str(self.val["direction"]).split("_")[-1].capitalize()
- if g_inherits_type(self.val, "GstGhostPad"):
- s += "Ghost"
- return s + "Pad"
-
- @save_memory_access_print("Pad(<inaccessible memory>)")
- def print(self, indent):
- m = ", " + self.mode() if self.mode() else ""
- _gdb_write(indent, "%s(%s%s) {" % (self.pad_type(), self.name(), m))
- first = True
- for ev in self.events():
- if first:
- _gdb_write(indent+1, "events:")
- first = False
- ev.print(indent+2)
-
- if self.is_linked():
- real = self.peer().parent_pad()
- _gdb_write(indent+1, "peer: %s" %
- (real.full_name() if real else self.peer().full_name()))
-
- if g_inherits_type(self.val, "GstGhostPad"):
- t = gdb.lookup_type("GstProxyPad").pointer()
- internal = GdbGstPad(self.val.cast(t)["priv"]["internal"])
- if internal and internal.peer():
- _gdb_write(indent+1, "inner peer: %s" %
- internal.peer().full_name())
-
- task = self.val["task"]
- if long(task) != 0:
- _gdb_write(indent+1, "task: %s" %
- task_state_to_name(int(task["state"])))
-
- offset = long(self.val["offset"])
- if offset != 0:
- _gdb_write(indent+1, "offset: %d [%s]" %
- (offset, format_time(offset, True)))
-
- _gdb_write(indent, "}")
-
- def _dot(self, color, pname, indent):
- spc = " " * indent
- activation_mode = "-><"
- style = "filled,solid"
- template = self.val["padtemplate"]
- if template != 0:
- presence = template["presence"]
- if str(presence) == "GST_PAD_SOMETIMES":
- style = "filled,dotted"
- if str(presence) == "GST_PAD_REQUEST":
- style = "filled,dashed"
- task_mode = ""
- task = self.val["task"]
- if long(task) != 0:
- task_state = int(task["state"])
- if task_state == 0: # started
- task_mode = "[T]"
- if task_state == 2: # paused
- task_mode = "[t]"
- f = int(self.val["object"]["flags"])
- flags = "B" if f & 16 else "b" # GST_PAD_FLAG_BLOCKED
- flags += "F" if f & 32 else "f" # GST_PAD_FLAG_FLUSHING
- flags += "B" if f & 16 else "b" # GST_PAD_FLAG_BLOCKING
-
- s = "%s %s_%s [color=black, fillcolor=\"%s\", " \
- "label=\"%s%s\\n[%c][%s]%s\", height=\"0.2\", style=\"%s\"];\n" % \
- (spc, pname, self.dot_name(), color, self.name(), "",
- activation_mode[int(self.val["mode"])], flags, task_mode, style)
- return s
-
- def dot(self, indent):
- spc = " " * indent
- direction = self.direction()
- element = self.parent_element()
- ename = element.dot_name() if element else ""
- s = ""
- if g_inherits_type(self.val, "GstGhostPad"):
- if direction == "GST_PAD_SRC":
- color = "#ffdddd"
- elif direction == "GST_PAD_SINK":
- color = "#ddddff"
- else:
- color = "#ffffff"
-
- t = gdb.lookup_type("GstProxyPad").pointer()
- other = GdbGstPad(self.val.cast(t)["priv"]["internal"])
- if other:
- s += other._dot(color, "", indent)
- pname = self.dot_name()
- other_element = other.parent_element()
- other_ename = other_element.dot_name() if other_element else ""
- other_pname = other.dot_name()
- if direction == "GST_PAD_SRC":
- s += "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n" % \
- (spc, other_ename, other_pname, ename, pname)
- else:
- s += "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n" % \
- (spc, ename, pname, other_ename, other_pname)
- else:
- if direction == "GST_PAD_SRC":
- color = "#ffaaaa"
- elif direction == "GST_PAD_SINK":
- color = "#aaaaff"
- else:
- color = "#cccccc"
-
- s += self._dot(color, ename, indent)
- return s
-
- def link_dot(self, indent, element):
- spc = " " * indent
-
- peer = self.peer()
- peer_element = peer.parent_element()
-
- caps = self.caps()
- if not caps:
- caps = self.template_caps()
- peer_caps = peer.caps()
- if not peer_caps:
- peer_caps = peer.template_caps()
-
- pname = self.dot_name()
- ename = element.dot_name() if element else ""
- peer_pname = peer.dot_name()
- peer_ename = peer_element.dot_name() if peer_element else ""
-
- if caps and peer_caps and caps == peer_caps:
- s = "%s%s_%s -> %s_%s [label=\"%s\"]\n" % \
- (spc, ename, pname, peer_ename, peer_pname, caps.dot())
- elif caps and peer_caps and caps != peer_caps:
- s = "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", " \
- % (spc, ename, pname, peer_ename, peer_pname)
- s += "label=\"" + " "*50 + "\", "
- if self.direction() == "GST_PAD_SRC":
- media_src = caps.dot()
- media_dst = peer_caps.dot()
- else:
- media_src = peer_caps.dot()
- media_dst = caps.dot()
- s += "taillabel=\"%s\", headlabel=\"%s\"]\n" % \
- (media_src, media_dst)
- else:
- s = "%s%s_%s -> %s_%s\n" % \
- (spc, ename, pname, peer_ename, peer_pname)
- return s
-
-
-class GdbGstElement(GdbGstObject):
- def __init__(self, val):
- gdb_type = gdb.lookup_type("GstElement").pointer()
- super(GdbGstElement, self).__init__(gdb_type, val)
- self.is_bin = gst_is_bin(self.val)
-
- def __eq__(self, other):
- return self.val == other.val
-
- def children(self):
- if not self.is_bin:
- return
- b = self.val.cast(gdb.lookup_type("GstBin").pointer())
- link = b["children"]
- while link != 0:
- yield GdbGstElement(link["data"])
- link = link["next"]
-
- def has_pads(self, pad_group="pads"):
- return self.val[pad_group] != 0
-
- def pads(self, pad_group="pads"):
- link = self.val[pad_group]
- while link != 0:
- yield GdbGstPad(link["data"])
- link = link["next"]
-
- def _state_dot(self):
- icons = "~0-=>"
- current = int(self.val["current_state"])
- pending = int(self.val["pending_state"])
- if pending == 0:
- # GST_ELEMENT_FLAG_LOCKED_STATE == 16
- locked = (int(self.val["object"]["flags"]) & 16) != 0
- return "\\n[%c]%s" % (icons[current], "(locked)" if locked else "")
- return "\\n[%c] -> [%c]" % (icons[current], icons[pending])
-
- @save_memory_access_print("Element(<inaccessible memory>)")
- def print(self, indent):
- _gdb_write(indent, "%s(%s) {" %
- (g_type_name_from_instance(self.val), self.name()))
- for p in self.pads():
- p.print(indent+2)
-
- first = True
- for child in self.children():
- if first:
- _gdb_write(indent+2, "children:")
- first = False
- _gdb_write(indent+3, child.name())
-
- current_state = self.val["current_state"]
- s = "state: %s" % element_state_to_name(current_state)
- for var in ("pending", "target"):
- state = self.val[var + "_state"]
- if state > 0 and state != current_state:
- s += ", %s: %s" % (var, element_state_to_name(state))
- _gdb_write(indent+2, s)
-
- _gdb_write(indent+2, "base_time: %s" %
- format_time_value(self.val["base_time"]))
- _gdb_write(indent+2, "start_time: %s" %
- format_time_value(self.val["start_time"]))
-
- _gdb_write(indent, "}")
-
- @save_memory_access_print("<inaccessible memory>")
- def print_tree(self, indent):
- _gdb_write(indent, "%s(%s)" % (self.name(), self.val))
- for child in self.children():
- child.print_tree(indent+1)
-
- def _dot(self, indent=0):
- spc = " " * indent
-
- s = "%ssubgraph cluster_%s {\n" % (spc, self.dot_name())
- s += "%s fontname=\"Bitstream Vera Sans\";\n" % spc
- s += "%s fontsize=\"8\";\n" % spc
- s += "%s style=\"filled,rounded\";\n" % spc
- s += "%s color=black;\n" % spc
- s += "%s label=\"%s\\n%s%s%s\";\n" % \
- (spc, g_type_name_from_instance(self.val), self.name(),
- self._state_dot(), "")
-
- sink_name = None
- if self.has_pads("sinkpads"):
- (ss, sink_name) = self._dot_pads(indent+1, "sinkpads",
- self.dot_name() + "_sink")
- s += ss
- src_name = None
- if self.has_pads("srcpads"):
- (ss, src_name) = self._dot_pads(indent+1, "srcpads",
- self.dot_name() + "_src")
- s += ss
- if sink_name and src_name:
- name = self.dot_name()
- s += "%s %s_%s -> %s_%s [style=\"invis\"];\n" % \
- (spc, name, sink_name, name, src_name)
-
- if gst_is_bin(self.val):
- s += "%s fillcolor=\"#ffffff\";\n" % spc
- s += self.dot(indent+1)
- else:
- if src_name and not sink_name:
- s += "%s fillcolor=\"#ffaaaa\";\n" % spc
- elif not src_name and sink_name:
- s += "%s fillcolor=\"#aaaaff\";\n" % spc
- elif src_name and sink_name:
- s += "%s fillcolor=\"#aaffaa\";\n" % spc
- else:
- s += "%s fillcolor=\"#ffffff\";\n" % spc
- s += "%s}\n\n" % spc
-
- for p in self.pads():
- if not p.is_linked():
- continue
- if p.direction() == "GST_PAD_SRC":
- s += p.link_dot(indent, self)
- else:
- pp = p.peer()
- if not g_inherits_type(pp.val, "GstGhostPad") and \
- g_inherits_type(pp.val, "GstProxyPad"):
- s += pp.link_dot(indent, None)
- return s
-
- def _dot_pads(self, indent, pad_group, cluster_name):
- spc = " " * indent
- s = "%ssubgraph cluster_%s {\n" % (spc, cluster_name)
- s += "%s label=\"\";\n" % spc
- s += "%s style=\"invis\";\n" % spc
- name = None
- for p in self.pads(pad_group):
- s += p.dot(indent)
- if not name:
- name = p.dot_name()
- s += "%s}\n\n" % spc
- return(s, name)
-
- def dot(self, indent):
- s = ""
- for child in self.children():
- try:
- s += child._dot(indent)
- except gdb.MemoryError:
- gdb.write("warning: inaccessible memory in element 0x%x\n" %
- long(child.val))
- return s
-
- def pipeline_dot(self):
- t = g_type_name_from_instance(self.val)
-
- s = "digraph pipeline {\n"
- s += " rankdir=LR;\n"
- s += " fontname=\"sans\";\n"
- s += " fontsize=\"10\";\n"
- s += " labelloc=t;\n"
- s += " nodesep=.1;\n"
- s += " ranksep=.2;\n"
- s += " label=\"<%s>\\n%s%s%s\";\n" % (t, self.name(), "", "")
- s += " node [style=\"filled,rounded\", shape=box, fontsize=\"9\", " \
- "fontname=\"sans\", margin=\"0.0,0.0\"];\n"
- s += " edge [labelfontsize=\"6\", fontsize=\"9\", " \
- "fontname=\"monospace\"];\n"
- s += " \n"
- s += " legend [\n"
- s += " pos=\"0,0!\",\n"
- s += " margin=\"0.05,0.05\",\n"
- s += " style=\"filled\",\n"
- s += " label=\"Legend\\lElement-States: [~] void-pending, " \
- "[0] null, [-] ready, [=] paused, [>] playing\\l" \
- "Pad-Activation: [-] none, [>] push, [<] pull\\l" \
- "Pad-Flags: [b]locked, [f]lushing, [b]locking, [E]OS; " \
- "upper-case is set\\lPad-Task: [T] has started task, " \
- "[t] has paused task\\l\",\n"
- s += " ];"
- s += "\n"
-
- s += self.dot(1)
-
- s += "}\n"
-
- return s
-
-
-class GstDot(gdb.Command):
- """\
-Create a pipeline dot file as close as possible to the output of
-GST_DEBUG_BIN_TO_DOT_FILE. This command will find the top-level parent
-for the given gstreamer object and create the dot for that element.
-
-Usage: gst-dot <gst-object> <file-name>"""
- def __init__(self):
- super(GstDot, self).__init__("gst-dot", gdb.COMMAND_DATA)
-
- def invoke(self, arg, from_tty):
- self.dont_repeat()
- args = gdb.string_to_argv(arg)
- if len(args) != 2:
- raise Exception("Usage: gst-dot <gst-object> <file>")
-
- value = gdb.parse_and_eval(args[0])
- if not value:
- raise Exception("'%s' is not a valid object" % args[0])
-
- value = gst_object_from_value(value)
- value = gst_object_pipeline(value)
-
- dot = GdbGstElement(value).pipeline_dot()
- file = open(args[1], "w")
- file.write(dot)
- file.close()
-
- def complete(self, text, word):
- cmd = gdb.string_to_argv(text)
- if len(cmd) == 0 or(len(cmd) == 1 and len(word) > 0):
- return gdb.COMPLETE_SYMBOL
- return gdb.COMPLETE_FILENAME
-
-
-class GstPrint(gdb.Command):
- """\
-Print high-level information for GStreamer objects
-
-Usage gst-print <gstreamer-object>"""
- def __init__(self):
- super(GstPrint, self).__init__("gst-print", gdb.COMMAND_DATA,
- gdb.COMPLETE_SYMBOL)
-
- def invoke(self, arg, from_tty):
- value = gdb.parse_and_eval(arg)
- if not value:
- raise Exception("'%s' is not a valid object" % arg)
-
- if value.type.code != gdb.TYPE_CODE_PTR:
- value = value.address
-
- if g_inherits_type(value, "GstElement"):
- obj = GdbGstElement(value)
- elif g_inherits_type(value, "GstPad"):
- obj = GdbGstPad(value)
- elif g_inherits_type(value, "GstCaps"):
- obj = GdbGstCaps(value)
- elif g_inherits_type(value, "GstEvent"):
- obj = GdbGstEvent(value)
- elif g_inherits_type(value, "GstQuery"):
- obj = GdbGstQuery(value)
- elif g_inherits_type(value, "GstBuffer"):
- obj = GdbGstBuffer(value)
- elif is_gst_type(value, "GstStructure"):
- obj = GdbGstStructure(value)
- else:
- raise Exception("'%s' has an unknown type (%s)" % (arg, value))
-
- obj.print(0)
-
-
-class GstPipelineTree(gdb.Command):
- """\
-Usage: gst-pipeline-tree <gst-object>"""
- def __init__(self):
- super(GstPipelineTree, self).__init__("gst-pipeline-tree",
- gdb.COMPLETE_SYMBOL)
-
- def invoke(self, arg, from_tty):
- self.dont_repeat()
- args = gdb.string_to_argv(arg)
- if len(args) != 1:
- raise Exception("Usage: gst-pipeline-tree <gst-object>")
-
- value = gdb.parse_and_eval(args[0])
- if not value:
- raise Exception("'%s' is not a valid object" % args[0])
-
- value = gst_object_from_value(value)
- value = gst_object_pipeline(value)
- GdbGstElement(value).print_tree(0)
-
-
-GstDot()
-GstPrint()
-GstPipelineTree()
-
-
-class GstPipeline(gdb.Function):
- """\
-Find the top-level pipeline for the given element"""
-
- def __init__(self):
- super(GstPipeline, self).__init__("gst_pipeline")
-
- def invoke(self, arg):
- value = gst_object_from_value(arg)
- return gst_object_pipeline(value)
-
-
-class GstBinGet(gdb.Function):
- """\
-Find a child element with the given name"""
-
- def __init__(self):
- super(GstBinGet, self).__init__("gst_bin_get")
-
- def find(self, obj, name, recurse):
- for child in obj.children():
- if child.name() == name:
- return child.val
- if recurse:
- result = self.find(child, name, recurse)
- if result is not None:
- return result
-
- def invoke(self, element, arg):
- value = gst_object_from_value(element)
- if not g_inherits_type(value, "GstElement"):
- raise Exception("'%s' is not a GstElement" %
- str(value.address))
-
- try:
- name = arg.string()
- except gdb.error:
- raise Exception("Usage: $gst_bin_get(<gst-object>, \"<name>\")")
-
- obj = GdbGstElement(value)
- child = self.find(obj, name, False)
- if child is None:
- child = self.find(obj, name, True)
- if child is None:
- raise Exception("No child named '%s' found." % name)
- return child
-
-
-class GstElementPad(gdb.Function):
- """\
-Get the pad with the given name"""
-
- def __init__(self):
- super(GstElementPad, self).__init__("gst_element_pad")
-
- def invoke(self, element, arg):
- value = gst_object_from_value(element)
- if not g_inherits_type(value, "GstElement"):
- raise Exception("'%s' is not a GstElement" %
- str(value.address))
-
- try:
- name = arg.string()
- except gdb.error:
- raise Exception("Usage: $gst_element_pad(<gst-object>, \"<pad-name>\")")
-
- obj = GdbGstElement(value)
- for pad in obj.pads():
- if pad.name() == name:
- return pad.val
-
- raise Exception("No pad named '%s' found." % name)
-
-
-GstPipeline()
-GstBinGet()
-GstElementPad()
-
-
-def register(obj):
- if obj is None:
- obj = gdb
-
- # Make sure this is always used before the glib lookup function.
- # Otherwise the gobject pretty printer is used for GstObjects
- obj.pretty_printers.insert(0, gst_pretty_printer_lookup)
diff --git a/libs/gst/helpers/libgstreamer-gdb.py.in b/libs/gst/helpers/libgstreamer-gdb.py.in
deleted file mode 100644
index 2cf65429fa..0000000000
--- a/libs/gst/helpers/libgstreamer-gdb.py.in
+++ /dev/null
@@ -1,10 +0,0 @@
-import sys
-import gdb
-
-# Update module path.
-dir_ = '@DATADIR@/gstreamer-@GST_API_VERSION@/gdb'
-if not dir_ in sys.path:
- sys.path.insert(0, dir_)
-
-from gst_gdb import register
-register (gdb.current_objfile ())
diff --git a/libs/gst/helpers/meson.build b/libs/gst/helpers/meson.build
deleted file mode 100644
index b34423f9c2..0000000000
--- a/libs/gst/helpers/meson.build
+++ /dev/null
@@ -1,143 +0,0 @@
-executable('gst-plugin-scanner',
- 'gst-plugin-scanner.c',
- c_args : gst_c_args,
- include_directories : [configinc],
- dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib, gst_dep],
- install_dir : helpers_install_dir,
- install: true,
-)
-
-# Used in test env setup to make tests find plugin scanner in build tree
-gst_scanner_dir = meson.current_build_dir()
-
-if bashcomp_found
- executable('gst-completion-helper',
- 'gst-completion-helper.c',
- c_args : gst_c_args,
- include_directories : [configinc],
- dependencies : [gobject_dep, glib_dep, gst_dep],
- install_dir : helpers_install_dir,
- install: true,
- )
-endif
-
-# Check PTP support
-have_ptp = false
-if host_system == 'android'
- message('PTP not supported on Android because of permissions.')
-elif host_system == 'windows'
- message('PTP not supported on Windows, not ported yet.')
-elif host_system == 'ios'
- message('PTP not supported on iOS because of permissions.')
-elif ['linux', 'darwin', 'netbsd', 'freebsd', 'openbsd', 'kfreebsd', 'dragonfly', 'sunos', 'gnu', 'gnu/kfreebsd'].contains(host_system)
- message('PTP supported on ' + host_system + '.')
- have_ptp = true
-else
- message('PTP not supported on ' + host_system + ', not ported yet.')
-endif
-
-if have_ptp
- cdata.set('HAVE_PTP', 1, description : 'PTP support available')
-
- if cc.compiles('''#include <sys/ioctl.h>
- #include <net/if.h>
- int some_func (void) {
- struct ifreq ifr;
- struct ifconf ifc;
- ioctl(0, SIOCGIFCONF, &ifc);
- ioctl(0, SIOCGIFFLAGS, &ifr);
- ioctl(0, SIOCGIFHWADDR, &ifr);
- return ifr.ifr_hwaddr.sa_data[0];
- }''',
- name : 'SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR available')
- cdata.set('HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR', 1,
- description : 'SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR is available')
- endif
-
- if cc.compiles('''#include <ifaddrs.h>
- #include <net/if.h>
- #include <net/if_dl.h>
- int some_func (void) {
- struct ifaddrs *ifaddr;
- getifaddrs(&ifaddr);
- return (ifaddr->ifa_flags & IFF_LOOPBACK) && ifaddr->ifa_addr->sa_family != AF_LINK;
- }''', name : 'getifaddrs() and AF_LINK available')
- cdata.set('HAVE_GETIFADDRS_AF_LINK', 1,
- description : 'getifaddrs() and AF_LINK is available')
- endif
-
- setcap_prog = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
- cap_dep = dependency('libcap', required: false)
-
- # user/group to change to in gst-ptp-helper
- ptp_helper_setuid_user = get_option('ptp-helper-setuid-user')
- if ptp_helper_setuid_user != ''
- cdata.set_quoted('HAVE_PTP_HELPER_SETUID_USER', ptp_helper_setuid_user,
- description : 'PTP helper setuid user')
- endif
- ptp_helper_setuid_group = get_option('ptp-helper-setuid-group')
- if ptp_helper_setuid_group != ''
- cdata.set_quoted('HAVE_PTP_HELPER_SETUID_GROUP', ptp_helper_setuid_group,
- description : 'PTP helper setuid group')
- endif
-
- # how to install gst-ptp-helper
- with_ptp_helper_permissions = get_option('ptp-helper-permissions')
- if with_ptp_helper_permissions == 'auto'
- if setcap_prog.found() and cap_dep.found()
- with_ptp_helper_permissions = 'capabilities'
- else
- with_ptp_helper_permissions = 'setuid-root'
- endif
- endif
- message('How to install gst-ptp-helper: ' + with_ptp_helper_permissions)
-
- if with_ptp_helper_permissions == 'none'
- # nothing to do
- elif with_ptp_helper_permissions == 'setuid-root'
- cdata.set('HAVE_PTP_HELPER_SETUID', 1,
- description : 'Use setuid-root for permissions in PTP helper')
- elif with_ptp_helper_permissions == 'capabilities'
- if not setcap_prog.found()
- error('capabilities-based ptp-helper-permissions requested, but could not find setcap tool.')
- elif not cap_dep.found()
- error('capabilities-based ptp-helper-permissions requested, but could not find libcap.')
- endif
- cdata.set('HAVE_PTP_HELPER_CAPABILITIES', 1,
- description : 'Use capabilities for permissions in PTP helper')
- else
- error('Unexpected ptp helper permissions value: ' + with_ptp_helper_permissions)
- endif
-
- executable('gst-ptp-helper', 'gst-ptp-helper.c',
- c_args : gst_c_args,
- include_directories : [configinc, libsinc],
- dependencies : [gio_dep, gobject_dep, glib_dep, mathlib, gst_dep, cap_dep],
- install_dir : helpers_install_dir,
- install : true)
-
- meson.add_install_script('ptp_helper_post_install.sh',
- helpers_install_dir, with_ptp_helper_permissions,
- setcap_prog.found() ? setcap_prog.path() : '')
-endif
-
-install_data(['gst_gdb.py', 'glib_gobject_helper.py'],
- install_dir : join_paths(get_option('datadir'), 'gstreamer-@0@'.format(apiversion), 'gdb'))
-
-gdbconf = configuration_data()
-gdbconf.set('GST_API_VERSION', apiversion)
-gdbconf.set('DATADIR', '@0@/@1@'.format(get_option('prefix'), get_option('datadir')))
-
-if host_system != 'windows'
- # XXX: We add a leading './' because prefix is an absolute path and we
- # need it to be a relative path so that join_paths appends it to the end.
- gdb_install_dir = join_paths(get_option('datadir'), 'gdb', 'auto-load', './' + get_option('prefix'), get_option('libdir'))
-else
- # FIXME: Cannot install on Windows because the path will contain a drive
- # letter and colons are not allowed in paths.
- gdb_install_dir = disabler()
-endif
-configure_file(input : 'libgstreamer-gdb.py.in',
- output : 'libgstreamer-@0@.so.@1@-gdb.py'.format(apiversion, libversion),
- install_dir : gdb_install_dir,
- configuration : gdbconf)
diff --git a/libs/gst/helpers/ptp_helper_post_install.sh b/libs/gst/helpers/ptp_helper_post_install.sh
deleted file mode 100755
index 4370acd956..0000000000
--- a/libs/gst/helpers/ptp_helper_post_install.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# Meson install script for gst-ptp-helper
-# Fails silently at the moment if setting permissions/capabilities doesn't work
-helpers_install_dir="$1"
-with_ptp_helper_permissions="$2"
-setcap="$3"
-
-ptp_helper="$MESON_INSTALL_DESTDIR_PREFIX/$helpers_install_dir/gst-ptp-helper"
-
-case "$with_ptp_helper_permissions" in
- setuid-root)
- echo "$0: permissions before: "
- ls -l "$ptp_helper"
- chown root "$ptp_helper" || true
- chmod u+s "$ptp_helper" || true
- echo "$0: permissions after: "
- ls -l "$ptp_helper"
- ;;
- capabilities)
- echo "Calling $setcap cap_net_bind_service,cap_net_admin+ep $ptp_helper"
- $setcap cap_net_bind_service,cap_net_admin+ep "$ptp_helper" || true
- ;;
- none)
- echo "No perms/caps to set for $ptp_helper"
- ;;
- *)
- echo "$0 ERROR: unexpected permissions value '$with_ptp_helper_permissions'";
- exit 2;
-esac
diff --git a/libs/gst/meson.build b/libs/gst/meson.build
deleted file mode 100644
index 33ecc2c274..0000000000
--- a/libs/gst/meson.build
+++ /dev/null
@@ -1,10 +0,0 @@
-subdir('base')
-subdir('controller')
-subdir('net')
-subdir('helpers')
-
-if get_option('check').disabled()
- gst_check_dep = dependency('', required : false)
-else
- subdir('check')
-endif
diff --git a/libs/gst/net/gstnet.h b/libs/gst/net/gstnet.h
deleted file mode 100644
index 28173809c2..0000000000
--- a/libs/gst/net/gstnet.h
+++ /dev/null
@@ -1,31 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NET_H__
-#define __GST_NET_H__
-
-#include <gst/net/net-prelude.h>
-
-#include <gst/net/gstnetaddressmeta.h>
-#include <gst/net/gstnetclientclock.h>
-#include <gst/net/gstnettimepacket.h>
-#include <gst/net/gstnettimeprovider.h>
-
-#endif /* __GST_NET_H__ */
diff --git a/libs/gst/net/gstnetaddressmeta.c b/libs/gst/net/gstnetaddressmeta.c
deleted file mode 100644
index 9867cac980..0000000000
--- a/libs/gst/net/gstnetaddressmeta.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* GStreamer
- * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstnetaddressmeta
- * @title: GstNetAddressMeta
- * @short_description: Network address metadata
- *
- * #GstNetAddressMeta can be used to store a network address (a #GSocketAddress)
- * in a #GstBuffer so that it network elements can track the to and from address
- * of the buffer.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "gstnetaddressmeta.h"
-
-static gboolean
-net_address_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer)
-{
- GstNetAddressMeta *nmeta = (GstNetAddressMeta *) meta;
-
- nmeta->addr = NULL;
-
- return TRUE;
-}
-
-static gboolean
-net_address_meta_transform (GstBuffer * transbuf, GstMeta * meta,
- GstBuffer * buffer, GQuark type, gpointer data)
-{
- GstNetAddressMeta *smeta, *dmeta;
- smeta = (GstNetAddressMeta *) meta;
-
- /* we always copy no matter what transform */
- dmeta = gst_buffer_add_net_address_meta (transbuf, smeta->addr);
- if (!dmeta)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-net_address_meta_free (GstMeta * meta, GstBuffer * buffer)
-{
- GstNetAddressMeta *nmeta = (GstNetAddressMeta *) meta;
-
- if (nmeta->addr)
- g_object_unref (nmeta->addr);
- nmeta->addr = NULL;
-}
-
-GType
-gst_net_address_meta_api_get_type (void)
-{
- static GType type;
- static const gchar *tags[] = { "origin", NULL };
-
- if (g_once_init_enter (&type)) {
- GType _type = gst_meta_api_type_register ("GstNetAddressMetaAPI", tags);
- g_once_init_leave (&type, _type);
- }
- return type;
-}
-
-const GstMetaInfo *
-gst_net_address_meta_get_info (void)
-{
- static const GstMetaInfo *meta_info = NULL;
-
- if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
- const GstMetaInfo *mi = gst_meta_register (GST_NET_ADDRESS_META_API_TYPE,
- "GstNetAddressMeta",
- sizeof (GstNetAddressMeta),
- net_address_meta_init,
- net_address_meta_free, net_address_meta_transform);
- g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi);
- }
- return meta_info;
-}
-
-/**
- * gst_buffer_add_net_address_meta:
- * @buffer: a #GstBuffer
- * @addr: a @GSocketAddress to connect to @buffer
- *
- * Attaches @addr as metadata in a #GstNetAddressMeta to @buffer.
- *
- * Returns: (transfer none): a #GstNetAddressMeta connected to @buffer
- */
-GstNetAddressMeta *
-gst_buffer_add_net_address_meta (GstBuffer * buffer, GSocketAddress * addr)
-{
- GstNetAddressMeta *meta;
-
- g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
- g_return_val_if_fail (G_IS_SOCKET_ADDRESS (addr), NULL);
-
- meta =
- (GstNetAddressMeta *) gst_buffer_add_meta (buffer,
- GST_NET_ADDRESS_META_INFO, NULL);
-
- meta->addr = g_object_ref (addr);
-
- return meta;
-}
-
-/**
- * gst_buffer_get_net_address_meta:
- * @buffer: a #GstBuffer
- *
- * Find the #GstNetAddressMeta on @buffer.
- *
- * Returns: (transfer none): the #GstNetAddressMeta or %NULL when there
- * is no such metadata on @buffer.
- */
-GstNetAddressMeta *
-gst_buffer_get_net_address_meta (GstBuffer * buffer)
-{
- return (GstNetAddressMeta *)
- gst_buffer_get_meta (buffer, GST_NET_ADDRESS_META_API_TYPE);
-}
diff --git a/libs/gst/net/gstnetaddressmeta.h b/libs/gst/net/gstnetaddressmeta.h
deleted file mode 100644
index e949b3117e..0000000000
--- a/libs/gst/net/gstnetaddressmeta.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* GStreamer
- * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_NET_ADDRESS_META_H__
-#define __GST_NET_ADDRESS_META_H__
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstNetAddressMeta GstNetAddressMeta;
-
-/**
- * GstNetAddressMeta:
- * @meta: the parent type
- * @addr: a #GSocketAddress stored as metadata
- *
- * Buffer metadata for network addresses.
- */
-struct _GstNetAddressMeta {
- GstMeta meta;
-
- GSocketAddress *addr;
-};
-
-GST_NET_API
-GType gst_net_address_meta_api_get_type (void);
-#define GST_NET_ADDRESS_META_API_TYPE (gst_net_address_meta_api_get_type())
-
-/* implementation */
-
-GST_NET_API
-const GstMetaInfo *gst_net_address_meta_get_info (void);
-#define GST_NET_ADDRESS_META_INFO (gst_net_address_meta_get_info())
-
-GST_NET_API
-GstNetAddressMeta * gst_buffer_add_net_address_meta (GstBuffer *buffer,
- GSocketAddress *addr);
-GST_NET_API
-GstNetAddressMeta * gst_buffer_get_net_address_meta (GstBuffer *buffer);
-
-G_END_DECLS
-
-#endif /* __GST_NET_ADDRESS_META_H__ */
-
diff --git a/libs/gst/net/gstnetclientclock.c b/libs/gst/net/gstnetclientclock.c
deleted file mode 100644
index 13ff01321e..0000000000
--- a/libs/gst/net/gstnetclientclock.c
+++ /dev/null
@@ -1,1492 +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>
- * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstnetclientclock
- * @title: GstNetClientClock
- * @short_description: Special clock that synchronizes to a remote time
- * provider.
- * @see_also: #GstClock, #GstNetTimeProvider, #GstPipeline
- *
- * #GstNetClientClock implements a custom #GstClock that synchronizes its time
- * to a remote time provider such as #GstNetTimeProvider. #GstNtpClock
- * implements a #GstClock that synchronizes its time to a remote NTPv4 server.
- *
- * A new clock is created with gst_net_client_clock_new() or
- * gst_ntp_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.
- *
- * The "round-trip" property limits the maximum round trip packets can take.
- *
- * Various parameters of the clock can be configured with the parent #GstClock
- * "timeout", "window-size" and "window-threshold" object properties.
- *
- * A #GstNetClientClock and #GstNtpClock is typically set on a #GstPipeline with
- * gst_pipeline_use_clock().
- *
- * If you set a #GstBus on the clock via the "bus" object property, it will
- * send @GST_MESSAGE_ELEMENT messages with an attached #GstStructure containing
- * statistics about clock accuracy and network traffic.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstnettimepacket.h"
-#include "gstntppacket.h"
-#include "gstnetclientclock.h"
-#include "gstnetutils.h"
-
-#include <gio/gio.h>
-
-#include <string.h>
-
-GST_DEBUG_CATEGORY_STATIC (ncc_debug);
-#define GST_CAT_DEFAULT (ncc_debug)
-
-typedef struct
-{
- GstClock *clock; /* GstNetClientInternalClock */
-
- GList *clocks; /* GstNetClientClocks */
-
- GstClockID remove_id;
-} ClockCache;
-
-G_LOCK_DEFINE_STATIC (clocks_lock);
-static GList *clocks = NULL;
-
-#define GST_TYPE_NET_CLIENT_INTERNAL_CLOCK \
- (gst_net_client_internal_clock_get_type())
-#define GST_NET_CLIENT_INTERNAL_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK,GstNetClientInternalClock))
-#define GST_NET_CLIENT_INTERNAL_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK,GstNetClientInternalClockClass))
-#define GST_IS_NET_CLIENT_INTERNAL_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK))
-#define GST_IS_NET_CLIENT_INTERNAL_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK))
-
-typedef struct _GstNetClientInternalClock GstNetClientInternalClock;
-typedef struct _GstNetClientInternalClockClass GstNetClientInternalClockClass;
-
-G_GNUC_INTERNAL GType gst_net_client_internal_clock_get_type (void);
-
-#define DEFAULT_ADDRESS "127.0.0.1"
-#define DEFAULT_PORT 5637
-#define DEFAULT_TIMEOUT GST_SECOND
-#define DEFAULT_ROUNDTRIP_LIMIT GST_SECOND
-/* Minimum timeout will be immediately (ie, as fast as one RTT), but no
- * more often than 1/20th second (arbitrarily, to spread observations a little) */
-#define DEFAULT_MINIMUM_UPDATE_INTERVAL (GST_SECOND / 20)
-#define DEFAULT_BASE_TIME 0
-#define DEFAULT_QOS_DSCP -1
-
-/* Maximum number of clock updates we can skip before updating */
-#define MAX_SKIPPED_UPDATES 5
-
-#define MEDIAN_PRE_FILTERING_WINDOW 9
-
-enum
-{
- PROP_0,
- PROP_ADDRESS,
- PROP_PORT,
- PROP_ROUNDTRIP_LIMIT,
- PROP_MINIMUM_UPDATE_INTERVAL,
- PROP_BUS,
- PROP_BASE_TIME,
- PROP_INTERNAL_CLOCK,
- PROP_IS_NTP,
- PROP_QOS_DSCP
-};
-
-struct _GstNetClientInternalClock
-{
- GstSystemClock clock;
-
- GThread *thread;
-
- GSocket *socket;
- GSocketAddress *servaddr;
- GCancellable *cancel;
- gboolean made_cancel_fd;
-
- GstClockTime timeout_expiration;
- GstClockTime roundtrip_limit;
- GstClockTime rtt_avg;
- GstClockTime minimum_update_interval;
- GstClockTime last_remote_poll_interval;
- guint skipped_updates;
- GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW];
- gint last_rtts_missing;
-
- gchar *address;
- gint port;
- gboolean is_ntp;
- gint qos_dscp;
-
- /* Protected by OBJECT_LOCK */
- GList *busses;
-};
-
-struct _GstNetClientInternalClockClass
-{
- GstSystemClockClass parent_class;
-};
-
-#define _do_init \
- GST_DEBUG_CATEGORY_INIT (ncc_debug, "netclock", 0, "Network client clock");
-
-G_DEFINE_TYPE_WITH_CODE (GstNetClientInternalClock,
- gst_net_client_internal_clock, GST_TYPE_SYSTEM_CLOCK, _do_init);
-
-static void gst_net_client_internal_clock_finalize (GObject * object);
-static void gst_net_client_internal_clock_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_net_client_internal_clock_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_net_client_internal_clock_constructed (GObject * object);
-
-static gboolean gst_net_client_internal_clock_start (GstNetClientInternalClock *
- self);
-static void gst_net_client_internal_clock_stop (GstNetClientInternalClock *
- self);
-
-static void
-gst_net_client_internal_clock_class_init (GstNetClientInternalClockClass *
- klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = gst_net_client_internal_clock_finalize;
- gobject_class->get_property = gst_net_client_internal_clock_get_property;
- gobject_class->set_property = gst_net_client_internal_clock_set_property;
- gobject_class->constructed = gst_net_client_internal_clock_constructed;
-
- g_object_class_install_property (gobject_class, PROP_ADDRESS,
- g_param_spec_string ("address", "address",
- "The IP address of the machine providing a time server",
- DEFAULT_ADDRESS,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, 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 | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_IS_NTP,
- g_param_spec_boolean ("is-ntp", "Is NTP",
- "The clock is using the NTPv4 protocol", FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gst_net_client_internal_clock_init (GstNetClientInternalClock * self)
-{
- GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC);
-
- self->port = DEFAULT_PORT;
- self->address = g_strdup (DEFAULT_ADDRESS);
- self->is_ntp = FALSE;
- self->qos_dscp = DEFAULT_QOS_DSCP;
-
- gst_clock_set_timeout (GST_CLOCK (self), DEFAULT_TIMEOUT);
-
- self->thread = NULL;
-
- self->servaddr = NULL;
- self->rtt_avg = GST_CLOCK_TIME_NONE;
- self->roundtrip_limit = DEFAULT_ROUNDTRIP_LIMIT;
- self->minimum_update_interval = DEFAULT_MINIMUM_UPDATE_INTERVAL;
- self->last_remote_poll_interval = GST_CLOCK_TIME_NONE;
- self->skipped_updates = 0;
- self->last_rtts_missing = MEDIAN_PRE_FILTERING_WINDOW;
-}
-
-static void
-gst_net_client_internal_clock_finalize (GObject * object)
-{
- GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object);
-
- if (self->thread) {
- gst_net_client_internal_clock_stop (self);
- }
-
- g_free (self->address);
- self->address = NULL;
-
- if (self->servaddr != NULL) {
- g_object_unref (self->servaddr);
- self->servaddr = NULL;
- }
-
- if (self->socket != NULL) {
- if (!g_socket_close (self->socket, NULL))
- GST_ERROR_OBJECT (self, "Failed to close socket");
- g_object_unref (self->socket);
- self->socket = NULL;
- }
-
- g_warn_if_fail (self->busses == NULL);
-
- G_OBJECT_CLASS (gst_net_client_internal_clock_parent_class)->finalize
- (object);
-}
-
-static void
-gst_net_client_internal_clock_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object);
-
- switch (prop_id) {
- case PROP_ADDRESS:
- GST_OBJECT_LOCK (self);
- g_free (self->address);
- self->address = g_value_dup_string (value);
- if (self->address == NULL)
- self->address = g_strdup (DEFAULT_ADDRESS);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_PORT:
- GST_OBJECT_LOCK (self);
- self->port = g_value_get_int (value);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_IS_NTP:
- GST_OBJECT_LOCK (self);
- self->is_ntp = g_value_get_boolean (value);
- GST_OBJECT_UNLOCK (self);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_net_client_internal_clock_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object);
-
- switch (prop_id) {
- case PROP_ADDRESS:
- GST_OBJECT_LOCK (self);
- g_value_set_string (value, self->address);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_PORT:
- g_value_set_int (value, self->port);
- break;
- case PROP_IS_NTP:
- g_value_set_boolean (value, self->is_ntp);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_net_client_internal_clock_constructed (GObject * object)
-{
- GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object);
-
- G_OBJECT_CLASS (gst_net_client_internal_clock_parent_class)->constructed
- (object);
-
- if (!gst_net_client_internal_clock_start (self)) {
- g_warning ("failed to start clock '%s'", GST_OBJECT_NAME (self));
- }
-
- /* all systems go, cap'n */
-}
-
-static gint
-compare_clock_time (const GstClockTime * a, const GstClockTime * b)
-{
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- return 0;
-}
-
-static void
-gst_net_client_internal_clock_observe_times (GstNetClientInternalClock * self,
- GstClockTime local_1, GstClockTime remote_1, GstClockTime remote_2,
- GstClockTime local_2)
-{
- GstClockTime current_timeout = 0;
- GstClockTime local_avg, remote_avg;
- gdouble r_squared;
- GstClock *clock;
- GstClockTime rtt, rtt_limit, min_update_interval;
- /* Use for discont tracking */
- GstClockTime time_before = 0;
- GstClockTime min_guess = 0;
- GstClockTimeDiff time_discont = 0;
- gboolean synched, now_synched;
- GstClockTime internal_time, external_time, rate_num, rate_den;
- GstClockTime orig_internal_time, orig_external_time, orig_rate_num,
- orig_rate_den;
- GstClockTime max_discont;
- GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW];
- GstClockTime median;
- gint i;
-
- GST_OBJECT_LOCK (self);
- rtt_limit = self->roundtrip_limit;
-
- GST_LOG_OBJECT (self,
- "local1 %" G_GUINT64_FORMAT " remote1 %" G_GUINT64_FORMAT " remote2 %"
- G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT, local_1, remote_1,
- remote_2, local_2);
-
- /* If the server told us a poll interval and it's bigger than the
- * one configured via the property, use the server's */
- if (self->last_remote_poll_interval != GST_CLOCK_TIME_NONE &&
- self->last_remote_poll_interval > self->minimum_update_interval)
- min_update_interval = self->last_remote_poll_interval;
- else
- min_update_interval = self->minimum_update_interval;
- GST_OBJECT_UNLOCK (self);
-
- if (local_2 < local_1) {
- GST_LOG_OBJECT (self, "Dropping observation: receive time %" GST_TIME_FORMAT
- " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (local_1),
- GST_TIME_ARGS (local_2));
- goto bogus_observation;
- }
-
- if (remote_2 < remote_1) {
- GST_LOG_OBJECT (self,
- "Dropping observation: remote receive time %" GST_TIME_FORMAT
- " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (remote_1),
- GST_TIME_ARGS (remote_2));
- goto bogus_observation;
- }
-
- /* The round trip time is (assuming symmetric path delays)
- * delta = (local_2 - local_1) - (remote_2 - remote_1)
- */
-
- rtt = GST_CLOCK_DIFF (local_1, local_2) - GST_CLOCK_DIFF (remote_1, remote_2);
-
- if ((rtt_limit > 0) && (rtt > rtt_limit)) {
- GST_LOG_OBJECT (self,
- "Dropping observation: RTT %" GST_TIME_FORMAT " > limit %"
- GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (rtt_limit));
- goto bogus_observation;
- }
-
- for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++)
- self->last_rtts[i - 1] = self->last_rtts[i];
- self->last_rtts[i - 1] = rtt;
-
- if (self->last_rtts_missing) {
- self->last_rtts_missing--;
- } else {
- memcpy (&last_rtts, &self->last_rtts, sizeof (last_rtts));
- g_qsort_with_data (&last_rtts,
- MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime),
- (GCompareDataFunc) compare_clock_time, NULL);
-
- median = last_rtts[MEDIAN_PRE_FILTERING_WINDOW / 2];
-
- /* FIXME: We might want to use something else here, like only allowing
- * things in the interquartile range, or also filtering away delays that
- * are too small compared to the median. This here worked well enough
- * in tests so far.
- */
- if (rtt > 2 * median) {
- GST_LOG_OBJECT (self,
- "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * median %"
- GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (median));
- goto bogus_observation;
- }
- }
-
- /* Track an average round trip time, for a bit of smoothing */
- /* Always update before discarding a sample, so genuine changes in
- * the network get picked up, eventually */
- if (self->rtt_avg == GST_CLOCK_TIME_NONE)
- self->rtt_avg = rtt;
- else if (rtt < self->rtt_avg) /* Shorter RTTs carry more weight than longer */
- self->rtt_avg = (3 * self->rtt_avg + rtt) / 4;
- else
- self->rtt_avg = (15 * self->rtt_avg + rtt) / 16;
-
- if (rtt > 2 * self->rtt_avg) {
- GST_LOG_OBJECT (self,
- "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * avg %"
- GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (self->rtt_avg));
- goto bogus_observation;
- }
-
- /* The difference between the local and remote clock (again assuming
- * symmetric path delays):
- *
- * local_1 + delta / 2 - remote_1 = theta
- * or
- * local_2 - delta / 2 - remote_2 = theta
- *
- * which gives after some simple algebraic transformations:
- *
- * (remote_1 - local_1) + (remote_2 - local_2)
- * theta = -------------------------------------------
- * 2
- *
- *
- * Thus remote time at local_avg is equal to:
- *
- * local_avg + theta =
- *
- * local_1 + local_2 (remote_1 - local_1) + (remote_2 - local_2)
- * ----------------- + -------------------------------------------
- * 2 2
- *
- * =
- *
- * remote_1 + remote_2
- * ------------------- = remote_avg
- * 2
- *
- * We use this for our clock estimation, i.e. local_avg at remote clock
- * being the same as remote_avg.
- */
-
- local_avg = (local_2 + local_1) / 2;
- remote_avg = (remote_2 + remote_1) / 2;
-
- GST_LOG_OBJECT (self,
- "remoteavg %" G_GUINT64_FORMAT " localavg %" G_GUINT64_FORMAT,
- remote_avg, local_avg);
-
- clock = GST_CLOCK_CAST (self);
-
- /* Store what the clock produced as 'now' before this update */
- gst_clock_get_calibration (GST_CLOCK_CAST (self), &orig_internal_time,
- &orig_external_time, &orig_rate_num, &orig_rate_den);
- internal_time = orig_internal_time;
- external_time = orig_external_time;
- rate_num = orig_rate_num;
- rate_den = orig_rate_den;
-
- min_guess =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_1,
- internal_time, external_time, rate_num, rate_den);
- time_before =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2,
- internal_time, external_time, rate_num, rate_den);
-
- /* Maximum discontinuity, when we're synched with the master. Could make this a property,
- * but this value seems to work fine */
- max_discont = self->rtt_avg / 4;
-
- /* If the remote observation was within a max_discont window around our min/max estimates, we're synched */
- synched =
- (GST_CLOCK_DIFF (remote_avg, min_guess) < (GstClockTimeDiff) (max_discont)
- && GST_CLOCK_DIFF (time_before,
- remote_avg) < (GstClockTimeDiff) (max_discont));
-
- if (gst_clock_add_observation_unapplied (GST_CLOCK_CAST (self),
- local_avg, remote_avg, &r_squared, &internal_time, &external_time,
- &rate_num, &rate_den)) {
-
- /* Now compare the difference (discont) in the clock
- * after this observation */
- time_discont = GST_CLOCK_DIFF (time_before,
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2,
- internal_time, external_time, rate_num, rate_den));
-
- /* If we were in sync with the remote clock, clamp the allowed
- * discontinuity to within quarter of one RTT. In sync means our send/receive estimates
- * of remote time correctly windowed the actual remote time observation */
- if (synched && ABS (time_discont) > max_discont) {
- GstClockTimeDiff offset;
- GST_DEBUG_OBJECT (clock,
- "Too large a discont, clamping to 1/4 average RTT = %"
- GST_TIME_FORMAT, GST_TIME_ARGS (max_discont));
- if (time_discont > 0) { /* Too large a forward step - add a -ve offset */
- offset = max_discont - time_discont;
- if (-offset > external_time)
- external_time = 0;
- else
- external_time += offset;
- } else { /* Too large a backward step - add a +ve offset */
- offset = -(max_discont + time_discont);
- external_time += offset;
- }
-
- time_discont += offset;
- }
-
- /* Check if the new clock params would have made our observation within range */
- now_synched =
- (GST_CLOCK_DIFF (remote_avg,
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self),
- local_1, internal_time, external_time, rate_num,
- rate_den)) < (GstClockTimeDiff) (max_discont))
- &&
- (GST_CLOCK_DIFF (gst_clock_adjust_with_calibration
- (GST_CLOCK_CAST (self), local_2, internal_time, external_time,
- rate_num, rate_den),
- remote_avg) < (GstClockTimeDiff) (max_discont));
-
- /* Only update the clock if we had synch or just gained it */
- if (synched || now_synched || self->skipped_updates > MAX_SKIPPED_UPDATES) {
- gst_clock_set_calibration (GST_CLOCK_CAST (self), internal_time,
- external_time, rate_num, rate_den);
- /* ghetto formula - shorter timeout for bad correlations */
- current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
- current_timeout =
- MIN (current_timeout, gst_clock_get_timeout (GST_CLOCK_CAST (self)));
- self->skipped_updates = 0;
-
- /* FIXME: When do we consider the clock absolutely not synced anymore? */
- gst_clock_set_synced (GST_CLOCK (self), TRUE);
- } else {
- /* Restore original calibration vars for the report, we're not changing the clock */
- internal_time = orig_internal_time;
- external_time = orig_external_time;
- rate_num = orig_rate_num;
- rate_den = orig_rate_den;
- time_discont = 0;
- self->skipped_updates++;
- }
- }
-
- /* Limit the polling to at most one per minimum_update_interval */
- if (rtt < min_update_interval)
- current_timeout = MAX (min_update_interval - rtt, current_timeout);
-
- GST_OBJECT_LOCK (self);
- if (self->busses) {
- GstStructure *s;
- GstMessage *msg;
- GList *l;
-
- /* Output a stats message, whether we updated the clock or not */
- s = gst_structure_new ("gst-netclock-statistics",
- "synchronised", G_TYPE_BOOLEAN, synched,
- "rtt", G_TYPE_UINT64, rtt,
- "rtt-average", G_TYPE_UINT64, self->rtt_avg,
- "local", G_TYPE_UINT64, local_avg,
- "remote", G_TYPE_UINT64, remote_avg,
- "discontinuity", G_TYPE_INT64, time_discont,
- "remote-min-estimate", G_TYPE_UINT64, min_guess,
- "remote-max-estimate", G_TYPE_UINT64, time_before,
- "remote-min-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote_avg,
- min_guess), "remote-max-error", G_TYPE_INT64,
- GST_CLOCK_DIFF (remote_avg, time_before), "request-send", G_TYPE_UINT64,
- local_1, "request-receive", G_TYPE_UINT64, local_2, "r-squared",
- G_TYPE_DOUBLE, r_squared, "timeout", G_TYPE_UINT64, current_timeout,
- "internal-time", G_TYPE_UINT64, internal_time, "external-time",
- G_TYPE_UINT64, external_time, "rate-num", G_TYPE_UINT64, rate_num,
- "rate-den", G_TYPE_UINT64, rate_den, "rate", G_TYPE_DOUBLE,
- (gdouble) (rate_num) / rate_den, "local-clock-offset", G_TYPE_INT64,
- GST_CLOCK_DIFF (internal_time, external_time), NULL);
- msg = gst_message_new_element (GST_OBJECT (self), s);
-
- for (l = self->busses; l; l = l->next)
- gst_bus_post (l->data, gst_message_ref (msg));
- gst_message_unref (msg);
- }
- GST_OBJECT_UNLOCK (self);
-
- GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout));
- self->timeout_expiration = gst_util_get_timestamp () + current_timeout;
-
- return;
-
-bogus_observation:
- /* Schedule a new packet again soon */
- self->timeout_expiration = gst_util_get_timestamp () + (GST_SECOND / 4);
- return;
-}
-
-static gpointer
-gst_net_client_internal_clock_thread (gpointer data)
-{
- GstNetClientInternalClock *self = data;
- GSocket *socket = self->socket;
- GError *err = NULL;
- gint cur_qos_dscp = DEFAULT_QOS_DSCP;
-
- GST_INFO_OBJECT (self, "net client clock thread running, socket=%p", socket);
-
- g_socket_set_blocking (socket, TRUE);
- g_socket_set_timeout (socket, 0);
-
- while (!g_cancellable_is_cancelled (self->cancel)) {
- GstClockTime expiration_time = self->timeout_expiration;
- GstClockTime now = gst_util_get_timestamp ();
- gint64 socket_timeout;
-
- if (now >= expiration_time || (expiration_time - now) <= GST_MSECOND) {
- socket_timeout = 0;
- } else {
- socket_timeout = (expiration_time - now) / GST_USECOND;
- }
-
- GST_TRACE_OBJECT (self, "timeout: %" G_GINT64_FORMAT "us", socket_timeout);
-
- if (!g_socket_condition_timed_wait (socket, G_IO_IN, socket_timeout,
- self->cancel, &err)) {
- /* cancelled, timeout or error */
- if (err->code == G_IO_ERROR_CANCELLED) {
- GST_INFO_OBJECT (self, "cancelled");
- g_clear_error (&err);
- break;
- } else if (err->code == G_IO_ERROR_TIMED_OUT) {
- gint new_qos_dscp;
-
- /* timed out, let's send another packet */
- GST_DEBUG_OBJECT (self, "timed out");
-
- /* before next sending check if need to change QoS */
- new_qos_dscp = self->qos_dscp;
- if (cur_qos_dscp != new_qos_dscp &&
- gst_net_utils_set_socket_tos (socket, new_qos_dscp)) {
- GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp);
- cur_qos_dscp = new_qos_dscp;
- }
-
- if (self->is_ntp) {
- GstNtpPacket *packet;
-
- packet = gst_ntp_packet_new (NULL, NULL);
-
- packet->transmit_time =
- gst_clock_get_internal_time (GST_CLOCK_CAST (self));
-
- GST_DEBUG_OBJECT (self,
- "sending packet, local time = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->transmit_time));
-
- gst_ntp_packet_send (packet, self->socket, self->servaddr, NULL);
-
- g_free (packet);
- } else {
- GstNetTimePacket *packet;
-
- packet = gst_net_time_packet_new (NULL);
-
- packet->local_time =
- gst_clock_get_internal_time (GST_CLOCK_CAST (self));
-
- GST_DEBUG_OBJECT (self,
- "sending packet, local time = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->local_time));
-
- gst_net_time_packet_send (packet, self->socket, self->servaddr, NULL);
-
- g_free (packet);
- }
-
- /* reset timeout (but are expecting a response sooner anyway) */
- self->timeout_expiration =
- gst_util_get_timestamp () +
- gst_clock_get_timeout (GST_CLOCK_CAST (self));
- } else {
- GST_DEBUG_OBJECT (self, "socket error: %s", err->message);
- g_usleep (G_USEC_PER_SEC / 10); /* throttle */
- }
- g_clear_error (&err);
- } else {
- GstClockTime new_local;
-
- /* got packet */
-
- new_local = gst_clock_get_internal_time (GST_CLOCK_CAST (self));
-
- if (self->is_ntp) {
- GstNtpPacket *packet;
-
- packet = gst_ntp_packet_receive (socket, NULL, &err);
-
- if (packet != NULL) {
- GST_LOG_OBJECT (self, "got packet back");
- GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->origin_time));
- GST_LOG_OBJECT (self, "remote_1 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->receive_time));
- GST_LOG_OBJECT (self, "remote_2 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->transmit_time));
- GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (new_local));
- GST_LOG_OBJECT (self, "poll_interval = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->poll_interval));
-
- /* Remember the last poll interval we ever got from the server */
- if (packet->poll_interval != GST_CLOCK_TIME_NONE)
- self->last_remote_poll_interval = packet->poll_interval;
-
- /* observe_times will reset the timeout */
- gst_net_client_internal_clock_observe_times (self,
- packet->origin_time, packet->receive_time, packet->transmit_time,
- new_local);
-
- g_free (packet);
- } else if (err != NULL) {
- if (g_error_matches (err, GST_NTP_ERROR, GST_NTP_ERROR_WRONG_VERSION)
- || g_error_matches (err, GST_NTP_ERROR, GST_NTP_ERROR_KOD_DENY)) {
- GST_ERROR_OBJECT (self, "fatal receive error: %s", err->message);
- g_clear_error (&err);
- break;
- } else if (g_error_matches (err, GST_NTP_ERROR,
- GST_NTP_ERROR_KOD_RATE)) {
- GST_WARNING_OBJECT (self, "need to limit rate");
-
- /* If the server did not tell us a poll interval before, double
- * our minimum poll interval. Otherwise we assume that the server
- * already told us something sensible and that this error here
- * was just a spurious error */
- if (self->last_remote_poll_interval == GST_CLOCK_TIME_NONE)
- self->minimum_update_interval *= 2;
-
- /* And wait a bit before we send the next packet instead of
- * sending it immediately */
- self->timeout_expiration =
- gst_util_get_timestamp () +
- gst_clock_get_timeout (GST_CLOCK_CAST (self));
- } else {
- GST_WARNING_OBJECT (self, "receive error: %s", err->message);
- }
- g_clear_error (&err);
- }
- } else {
- GstNetTimePacket *packet;
-
- packet = gst_net_time_packet_receive (socket, NULL, &err);
-
- if (packet != NULL) {
- GST_LOG_OBJECT (self, "got packet back");
- GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->local_time));
- GST_LOG_OBJECT (self, "remote = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (packet->remote_time));
- GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT,
- GST_TIME_ARGS (new_local));
-
- /* observe_times will reset the timeout */
- gst_net_client_internal_clock_observe_times (self, packet->local_time,
- packet->remote_time, packet->remote_time, new_local);
-
- g_free (packet);
- } else if (err != NULL) {
- GST_WARNING_OBJECT (self, "receive error: %s", err->message);
- g_clear_error (&err);
- }
- }
- }
- }
- GST_INFO_OBJECT (self, "shutting down net client clock thread");
- return NULL;
-}
-
-static gboolean
-gst_net_client_internal_clock_start (GstNetClientInternalClock * self)
-{
- GSocketAddress *servaddr;
- GSocketAddress *myaddr;
- GSocketAddress *anyaddr;
- GInetAddress *inetaddr;
- GSocket *socket;
- GError *error = NULL;
- GSocketFamily family;
- GPollFD dummy_pollfd;
- GResolver *resolver = NULL;
- GError *err = NULL;
-
- g_return_val_if_fail (self->address != NULL, FALSE);
- g_return_val_if_fail (self->servaddr == NULL, FALSE);
-
- /* create target address */
- inetaddr = g_inet_address_new_from_string (self->address);
- if (inetaddr == NULL) {
- GList *results;
-
- resolver = g_resolver_get_default ();
-
- results = g_resolver_lookup_by_name (resolver, self->address, NULL, &err);
- if (!results)
- goto failed_to_resolve;
-
- inetaddr = G_INET_ADDRESS (g_object_ref (results->data));
- g_resolver_free_addresses (results);
- g_object_unref (resolver);
- }
-
- family = g_inet_address_get_family (inetaddr);
-
- servaddr = g_inet_socket_address_new (inetaddr, self->port);
- g_object_unref (inetaddr);
-
- g_assert (servaddr != NULL);
-
- GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address,
- self->port);
-
- socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM,
- G_SOCKET_PROTOCOL_UDP, &error);
-
- if (socket == NULL)
- goto no_socket;
-
- GST_DEBUG_OBJECT (self, "binding socket");
- inetaddr = g_inet_address_new_any (family);
- anyaddr = g_inet_socket_address_new (inetaddr, 0);
- g_socket_bind (socket, anyaddr, TRUE, &error);
- g_object_unref (anyaddr);
- g_object_unref (inetaddr);
-
- if (error != NULL)
- goto bind_error;
-
- /* check address we're bound to, mostly for debugging purposes */
- myaddr = g_socket_get_local_address (socket, &error);
-
- if (myaddr == NULL)
- goto getsockname_error;
-
- GST_DEBUG_OBJECT (self, "socket opened on UDP port %d",
- g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr)));
-
- g_object_unref (myaddr);
-
- self->cancel = g_cancellable_new ();
- self->made_cancel_fd =
- g_cancellable_make_pollfd (self->cancel, &dummy_pollfd);
-
- self->socket = socket;
- self->servaddr = G_SOCKET_ADDRESS (servaddr);
-
- self->thread = g_thread_try_new ("GstNetClientInternalClock",
- gst_net_client_internal_clock_thread, self, &error);
-
- if (error != NULL)
- goto no_thread;
-
- return TRUE;
-
- /* ERRORS */
-no_socket:
- {
- GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message);
- g_error_free (error);
- return FALSE;
- }
-bind_error:
- {
- GST_ERROR_OBJECT (self, "bind failed: %s", error->message);
- g_error_free (error);
- g_object_unref (socket);
- return FALSE;
- }
-getsockname_error:
- {
- GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message);
- g_error_free (error);
- g_object_unref (socket);
- return FALSE;
- }
-failed_to_resolve:
- {
- GST_ERROR_OBJECT (self, "resolving '%s' failed: %s",
- self->address, err->message);
- g_clear_error (&err);
- g_object_unref (resolver);
- return FALSE;
- }
-no_thread:
- {
- GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
- g_object_unref (self->servaddr);
- self->servaddr = NULL;
- g_object_unref (self->socket);
- self->socket = NULL;
- g_error_free (error);
- return FALSE;
- }
-}
-
-static void
-gst_net_client_internal_clock_stop (GstNetClientInternalClock * self)
-{
- if (self->thread == NULL)
- return;
-
- GST_INFO_OBJECT (self, "stopping...");
- g_cancellable_cancel (self->cancel);
-
- g_thread_join (self->thread);
- self->thread = NULL;
-
- if (self->made_cancel_fd)
- g_cancellable_release_fd (self->cancel);
-
- g_object_unref (self->cancel);
- self->cancel = NULL;
-
- g_object_unref (self->servaddr);
- self->servaddr = NULL;
-
- g_object_unref (self->socket);
- self->socket = NULL;
-
- GST_INFO_OBJECT (self, "stopped");
-}
-
-struct _GstNetClientClockPrivate
-{
- GstClock *internal_clock;
-
- GstClockTime roundtrip_limit;
- GstClockTime minimum_update_interval;
-
- GstClockTime base_time, internal_base_time;
-
- gchar *address;
- gint port;
- gint qos_dscp;
-
- GstBus *bus;
-
- gboolean is_ntp;
-
- gulong synced_id;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GstNetClientClock, gst_net_client_clock,
- GST_TYPE_SYSTEM_CLOCK);
-
-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_constructed (GObject * object);
-
-static GstClockTime gst_net_client_clock_get_internal_time (GstClock * clock);
-
-static void
-gst_net_client_clock_class_init (GstNetClientClockClass * klass)
-{
- GObjectClass *gobject_class;
- GstClockClass *clock_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- clock_class = GST_CLOCK_CLASS (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;
- gobject_class->constructed = gst_net_client_clock_constructed;
-
- g_object_class_install_property (gobject_class, PROP_ADDRESS,
- g_param_spec_string ("address", "address",
- "The IP address of the machine providing a time server",
- DEFAULT_ADDRESS,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, 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 | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_BUS,
- g_param_spec_object ("bus", "bus",
- "A GstBus on which to send clock status information", GST_TYPE_BUS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /**
- * GstNetClientInternalClock::round-trip-limit:
- *
- * Maximum allowed round-trip for packets. If this property is set to a nonzero
- * value, all packets with a round-trip interval larger than this limit will be
- * ignored. This is useful for networks with severe and fluctuating transport
- * delays. Filtering out these packets increases stability of the synchronization.
- * On the other hand, the lower the limit, the higher the amount of filtered
- * packets. Empirical tests are typically necessary to estimate a good value
- * for the limit.
- * If the property is set to zero, the limit is disabled.
- *
- * Since: 1.4
- */
- g_object_class_install_property (gobject_class, PROP_ROUNDTRIP_LIMIT,
- g_param_spec_uint64 ("round-trip-limit", "round-trip limit",
- "Maximum tolerable round-trip interval for packets, in nanoseconds "
- "(0 = no limit)", 0, G_MAXUINT64, DEFAULT_ROUNDTRIP_LIMIT,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_MINIMUM_UPDATE_INTERVAL,
- g_param_spec_uint64 ("minimum-update-interval", "minimum update interval",
- "Minimum polling interval for packets, in nanoseconds"
- "(0 = no limit)", 0, G_MAXUINT64, DEFAULT_MINIMUM_UPDATE_INTERVAL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_BASE_TIME,
- g_param_spec_uint64 ("base-time", "Base Time",
- "Initial time that is reported before synchronization", 0,
- G_MAXUINT64, DEFAULT_BASE_TIME,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_INTERNAL_CLOCK,
- g_param_spec_object ("internal-clock", "Internal Clock",
- "Internal clock that directly slaved to the remote clock",
- GST_TYPE_CLOCK, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_QOS_DSCP,
- g_param_spec_int ("qos-dscp", "QoS diff srv code point",
- "Quality of Service, differentiated services code point (-1 default)",
- -1, 63, DEFAULT_QOS_DSCP,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- clock_class->get_internal_time = gst_net_client_clock_get_internal_time;
-}
-
-static void
-gst_net_client_clock_init (GstNetClientClock * self)
-{
- GstNetClientClockPrivate *priv;
- GstClock *clock;
-
- self->priv = priv = gst_net_client_clock_get_instance_private (self);
-
- GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_CAN_SET_MASTER);
- GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC);
-
- priv->port = DEFAULT_PORT;
- priv->address = g_strdup (DEFAULT_ADDRESS);
- priv->qos_dscp = DEFAULT_QOS_DSCP;
-
- priv->roundtrip_limit = DEFAULT_ROUNDTRIP_LIMIT;
- priv->minimum_update_interval = DEFAULT_MINIMUM_UPDATE_INTERVAL;
-
- clock = gst_system_clock_obtain ();
- priv->base_time = DEFAULT_BASE_TIME;
- priv->internal_base_time = gst_clock_get_time (clock);
- gst_object_unref (clock);
-}
-
-/* Must be called with clocks_lock */
-static void
-update_clock_cache (ClockCache * cache)
-{
- GstClockTime roundtrip_limit = 0, minimum_update_interval = 0;
- GList *l, *busses = NULL;
- gint qos_dscp = DEFAULT_QOS_DSCP;
-
- GST_OBJECT_LOCK (cache->clock);
- g_list_free_full (GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->busses,
- (GDestroyNotify) gst_object_unref);
-
- for (l = cache->clocks; l; l = l->next) {
- GstNetClientClock *clock = l->data;
-
- if (clock->priv->bus)
- busses = g_list_prepend (busses, gst_object_ref (clock->priv->bus));
-
- if (roundtrip_limit == 0)
- roundtrip_limit = clock->priv->roundtrip_limit;
- else
- roundtrip_limit = MAX (roundtrip_limit, clock->priv->roundtrip_limit);
-
- if (minimum_update_interval == 0)
- minimum_update_interval = clock->priv->minimum_update_interval;
- else
- minimum_update_interval =
- MIN (minimum_update_interval, clock->priv->minimum_update_interval);
-
- qos_dscp = MAX (qos_dscp, clock->priv->qos_dscp);
- }
- GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->busses = busses;
- GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->roundtrip_limit =
- roundtrip_limit;
- GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->minimum_update_interval =
- minimum_update_interval;
- GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->qos_dscp = qos_dscp;
-
- GST_OBJECT_UNLOCK (cache->clock);
-}
-
-static gboolean
-remove_clock_cache (GstClock * clock, GstClockTime time, GstClockID id,
- gpointer user_data)
-{
- ClockCache *cache = user_data;
-
- G_LOCK (clocks_lock);
- if (!cache->clocks) {
- gst_clock_id_unref (cache->remove_id);
- gst_object_unref (cache->clock);
- clocks = g_list_remove (clocks, cache);
- g_free (cache);
- }
- G_UNLOCK (clocks_lock);
-
- return TRUE;
-}
-
-static void
-gst_net_client_clock_finalize (GObject * object)
-{
- GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
- GList *l;
-
- if (self->priv->synced_id)
- g_signal_handler_disconnect (self->priv->internal_clock,
- self->priv->synced_id);
- self->priv->synced_id = 0;
-
- G_LOCK (clocks_lock);
- for (l = clocks; l; l = l->next) {
- ClockCache *cache = l->data;
-
- if (cache->clock == self->priv->internal_clock) {
- cache->clocks = g_list_remove (cache->clocks, self);
-
- if (cache->clocks) {
- update_clock_cache (cache);
- } else {
- GstClock *sysclock = gst_system_clock_obtain ();
- GstClockTime time = gst_clock_get_time (sysclock) + 60 * GST_SECOND;
-
- cache->remove_id = gst_clock_new_single_shot_id (sysclock, time);
- gst_clock_id_wait_async (cache->remove_id, remove_clock_cache, cache,
- NULL);
- gst_object_unref (sysclock);
- }
- break;
- }
- }
- G_UNLOCK (clocks_lock);
-
- g_free (self->priv->address);
- self->priv->address = NULL;
-
- if (self->priv->bus != NULL) {
- gst_object_unref (self->priv->bus);
- self->priv->bus = NULL;
- }
-
- G_OBJECT_CLASS (gst_net_client_clock_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);
- gboolean update = FALSE;
-
- switch (prop_id) {
- case PROP_ADDRESS:
- GST_OBJECT_LOCK (self);
- g_free (self->priv->address);
- self->priv->address = g_value_dup_string (value);
- if (self->priv->address == NULL)
- self->priv->address = g_strdup (DEFAULT_ADDRESS);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_PORT:
- GST_OBJECT_LOCK (self);
- self->priv->port = g_value_get_int (value);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_ROUNDTRIP_LIMIT:
- GST_OBJECT_LOCK (self);
- self->priv->roundtrip_limit = g_value_get_uint64 (value);
- GST_OBJECT_UNLOCK (self);
- update = TRUE;
- break;
- case PROP_MINIMUM_UPDATE_INTERVAL:
- GST_OBJECT_LOCK (self);
- self->priv->minimum_update_interval = g_value_get_uint64 (value);
- GST_OBJECT_UNLOCK (self);
- update = TRUE;
- break;
- case PROP_BUS:
- GST_OBJECT_LOCK (self);
- if (self->priv->bus)
- gst_object_unref (self->priv->bus);
- self->priv->bus = g_value_dup_object (value);
- GST_OBJECT_UNLOCK (self);
- update = TRUE;
- break;
- case PROP_BASE_TIME:{
- GstClock *clock;
-
- self->priv->base_time = g_value_get_uint64 (value);
- clock = gst_system_clock_obtain ();
- self->priv->internal_base_time = gst_clock_get_time (clock);
- gst_object_unref (clock);
- break;
- }
- case PROP_QOS_DSCP:
- GST_OBJECT_LOCK (self);
- self->priv->qos_dscp = g_value_get_int (value);
- GST_OBJECT_UNLOCK (self);
- update = TRUE;
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- if (update && self->priv->internal_clock) {
- GList *l;
-
- G_LOCK (clocks_lock);
- for (l = clocks; l; l = l->next) {
- ClockCache *cache = l->data;
-
- if (cache->clock == self->priv->internal_clock) {
- update_clock_cache (cache);
- }
- }
- G_UNLOCK (clocks_lock);
- }
-}
-
-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:
- GST_OBJECT_LOCK (self);
- g_value_set_string (value, self->priv->address);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_PORT:
- g_value_set_int (value, self->priv->port);
- break;
- case PROP_ROUNDTRIP_LIMIT:
- GST_OBJECT_LOCK (self);
- g_value_set_uint64 (value, self->priv->roundtrip_limit);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_MINIMUM_UPDATE_INTERVAL:
- GST_OBJECT_LOCK (self);
- g_value_set_uint64 (value, self->priv->minimum_update_interval);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_BUS:
- GST_OBJECT_LOCK (self);
- g_value_set_object (value, self->priv->bus);
- GST_OBJECT_UNLOCK (self);
- break;
- case PROP_BASE_TIME:
- g_value_set_uint64 (value, self->priv->base_time);
- break;
- case PROP_INTERNAL_CLOCK:
- g_value_set_object (value, self->priv->internal_clock);
- break;
- case PROP_QOS_DSCP:
- GST_OBJECT_LOCK (self);
- g_value_set_int (value, self->priv->qos_dscp);
- GST_OBJECT_UNLOCK (self);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_net_client_clock_synced_cb (GstClock * internal_clock, gboolean synced,
- GstClock * self)
-{
- gst_clock_set_synced (self, synced);
-}
-
-static void
-gst_net_client_clock_constructed (GObject * object)
-{
- GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
- GstClock *internal_clock;
- GList *l;
- ClockCache *cache = NULL;
-
- G_OBJECT_CLASS (gst_net_client_clock_parent_class)->constructed (object);
-
- G_LOCK (clocks_lock);
- for (l = clocks; l; l = l->next) {
- ClockCache *tmp = l->data;
- GstNetClientInternalClock *internal_clock =
- GST_NET_CLIENT_INTERNAL_CLOCK (tmp->clock);
-
- if (strcmp (internal_clock->address, self->priv->address) == 0 &&
- internal_clock->port == self->priv->port) {
- cache = tmp;
-
- if (cache->remove_id) {
- gst_clock_id_unschedule (cache->remove_id);
- cache->remove_id = NULL;
- }
- break;
- }
- }
-
- if (!cache) {
- cache = g_new0 (ClockCache, 1);
-
- cache->clock =
- g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, "address",
- self->priv->address, "port", self->priv->port, "is-ntp",
- self->priv->is_ntp, NULL);
- gst_object_ref_sink (cache->clock);
- clocks = g_list_prepend (clocks, cache);
-
- /* Not actually leaked but is cached for a while before being disposed,
- * see gst_net_client_clock_finalize, so pretend it is to not confuse
- * tests. */
- GST_OBJECT_FLAG_SET (cache->clock, GST_OBJECT_FLAG_MAY_BE_LEAKED);
- }
-
- cache->clocks = g_list_prepend (cache->clocks, self);
-
- GST_OBJECT_LOCK (cache->clock);
- if (gst_clock_is_synced (cache->clock))
- gst_clock_set_synced (GST_CLOCK (self), TRUE);
- self->priv->synced_id =
- g_signal_connect (cache->clock, "synced",
- G_CALLBACK (gst_net_client_clock_synced_cb), self);
- GST_OBJECT_UNLOCK (cache->clock);
-
- G_UNLOCK (clocks_lock);
-
- self->priv->internal_clock = internal_clock = cache->clock;
-
- /* all systems go, cap'n */
-}
-
-static GstClockTime
-gst_net_client_clock_get_internal_time (GstClock * clock)
-{
- GstNetClientClock *self = GST_NET_CLIENT_CLOCK (clock);
-
- if (!gst_clock_is_synced (self->priv->internal_clock)) {
- GstClockTime now = gst_clock_get_internal_time (self->priv->internal_clock);
- return gst_clock_adjust_with_calibration (self->priv->internal_clock, now,
- self->priv->internal_base_time, self->priv->base_time, 1, 1);
- }
-
- return gst_clock_get_time (self->priv->internal_clock);
-}
-
-/**
- * gst_net_client_clock_new:
- * @name: a name for the clock
- * @remote_address: the address or hostname 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 #GstNetTimeProvider on @remote_address and
- * @remote_port.
- *
- * Returns: (transfer full): a new #GstClock that receives a time from the remote
- * clock.
- */
-GstClock *
-gst_net_client_clock_new (const gchar * name, const gchar * remote_address,
- gint remote_port, GstClockTime base_time)
-{
- GstClock *ret;
-
- 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, "name", name, "address",
- remote_address, "port", remote_port, "base-time", base_time, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (ret);
-
- return ret;
-}
-
-G_DEFINE_TYPE (GstNtpClock, gst_ntp_clock, GST_TYPE_NET_CLIENT_CLOCK);
-
-static void
-gst_ntp_clock_class_init (GstNtpClockClass * klass)
-{
-}
-
-static void
-gst_ntp_clock_init (GstNtpClock * self)
-{
- GST_NET_CLIENT_CLOCK (self)->priv->is_ntp = TRUE;
-}
-
-/**
- * gst_ntp_clock_new:
- * @name: a name for the clock
- * @remote_address: the address or hostname of the remote clock provider
- * @remote_port: the port of the remote clock provider
- * @base_time: initial time of the clock
- *
- * Create a new #GstNtpClock that will report the time provided by
- * the NTPv4 server on @remote_address and @remote_port.
- *
- * Returns: (transfer full): a new #GstClock that receives a time from the remote
- * clock.
- *
- * Since: 1.6
- */
-GstClock *
-gst_ntp_clock_new (const gchar * name, const gchar * remote_address,
- gint remote_port, GstClockTime base_time)
-{
- GstClock *ret;
-
- 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_NTP_CLOCK, "name", name, "address", remote_address,
- "port", remote_port, "base-time", base_time, NULL);
-
- gst_object_ref_sink (ret);
-
- return ret;
-}
diff --git a/libs/gst/net/gstnetclientclock.h b/libs/gst/net/gstnetclientclock.h
deleted file mode 100644
index 506270c7d5..0000000000
--- a/libs/gst/net/gstnetclientclock.h
+++ /dev/null
@@ -1,106 +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>
- * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NET_CLIENT_CLOCK_H__
-#define __GST_NET_CLIENT_CLOCK_H__
-
-#include <gst/gst.h>
-#include <gst/gstsystemclock.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-#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(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_CLIENT_CLOCK))
-
-typedef struct _GstNetClientClock GstNetClientClock;
-typedef struct _GstNetClientClockClass GstNetClientClockClass;
-typedef struct _GstNetClientClockPrivate GstNetClientClockPrivate;
-
-/**
- * GstNetClientClock:
- *
- * Opaque #GstNetClientClock structure.
- */
-struct _GstNetClientClock {
- GstSystemClock clock;
-
- /*< private >*/
- GstNetClientClockPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstNetClientClockClass {
- GstSystemClockClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_NET_API
-GType gst_net_client_clock_get_type (void);
-
-GST_NET_API
-GstClock* gst_net_client_clock_new (const gchar *name, const gchar *remote_address,
- gint remote_port, GstClockTime base_time);
-
-#define GST_TYPE_NTP_CLOCK \
- (gst_ntp_clock_get_type())
-#define GST_NTP_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NTP_CLOCK,GstNtpClock))
-#define GST_NTP_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NTP_CLOCK,GstNtpClockClass))
-#define GST_IS_NTP_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NTP_CLOCK))
-#define GST_IS_NTP_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NTP_CLOCK))
-
-typedef struct _GstNetClientClock GstNtpClock;
-typedef struct _GstNetClientClockClass GstNtpClockClass;
-
-GST_NET_API
-GType gst_ntp_clock_get_type (void);
-
-GST_NET_API
-GstClock* gst_ntp_clock_new (const gchar *name, const gchar *remote_address,
- gint remote_port, GstClockTime base_time);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetClientClock, gst_object_unref)
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNtpClock, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_NET_CLIENT_CLOCK_H__ */
diff --git a/libs/gst/net/gstnetcontrolmessagemeta.c b/libs/gst/net/gstnetcontrolmessagemeta.c
deleted file mode 100644
index f4d2a2912f..0000000000
--- a/libs/gst/net/gstnetcontrolmessagemeta.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* GStreamer
- * Copyright (C) <2014> William Manley <will@williammanley.net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:gstnetcontrolmessagemeta
- * @title: GstNetControlMessageMeta
- * @short_description: Network Control Message Meta
- *
- * #GstNetControlMessageMeta can be used to store control messages (ancillary
- * data) which was received with or is to be sent alongside the buffer data.
- * When used with socket sinks and sources which understand this meta it allows
- * sending and receiving ancillary data such as unix credentials (See
- * #GUnixCredentialsMessage) and Unix file descriptions (See #GUnixFDMessage).
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "gstnetcontrolmessagemeta.h"
-
-static gboolean
-net_control_message_meta_init (GstMeta * meta, gpointer params,
- GstBuffer * buffer)
-{
- GstNetControlMessageMeta *nmeta = (GstNetControlMessageMeta *) meta;
-
- nmeta->message = NULL;
-
- return TRUE;
-}
-
-static gboolean
-net_control_message_meta_transform (GstBuffer * transbuf, GstMeta * meta,
- GstBuffer * buffer, GQuark type, gpointer data)
-{
- GstNetControlMessageMeta *smeta, *dmeta;
- smeta = (GstNetControlMessageMeta *) meta;
-
- /* we always copy no matter what transform */
- dmeta = gst_buffer_add_net_control_message_meta (transbuf, smeta->message);
- if (!dmeta)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-net_control_message_meta_free (GstMeta * meta, GstBuffer * buffer)
-{
- GstNetControlMessageMeta *nmeta = (GstNetControlMessageMeta *) meta;
-
- if (nmeta->message)
- g_object_unref (nmeta->message);
- nmeta->message = NULL;
-}
-
-GType
-gst_net_control_message_meta_api_get_type (void)
-{
- static GType type;
- static const gchar *tags[] = { "origin", NULL };
-
- if (g_once_init_enter (&type)) {
- GType _type =
- gst_meta_api_type_register ("GstNetControlMessageMetaAPI", tags);
- g_once_init_leave (&type, _type);
- }
- return type;
-}
-
-const GstMetaInfo *
-gst_net_control_message_meta_get_info (void)
-{
- static const GstMetaInfo *meta_info = NULL;
-
- if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
- const GstMetaInfo *mi =
- gst_meta_register (GST_NET_CONTROL_MESSAGE_META_API_TYPE,
- "GstNetControlMessageMeta",
- sizeof (GstNetControlMessageMeta),
- net_control_message_meta_init,
- net_control_message_meta_free,
- net_control_message_meta_transform);
- g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi);
- }
- return meta_info;
-}
-
-/**
- * gst_buffer_add_net_control_message_meta:
- * @buffer: a #GstBuffer
- * @message: a @GSocketControlMessage to attach to @buffer
- *
- * Attaches @message as metadata in a #GstNetControlMessageMeta to @buffer.
- *
- * Returns: (transfer none): a #GstNetControlMessageMeta connected to @buffer
- */
-GstNetControlMessageMeta *
-gst_buffer_add_net_control_message_meta (GstBuffer * buffer,
- GSocketControlMessage * message)
-{
- GstNetControlMessageMeta *meta;
-
- g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
- g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), NULL);
-
- meta =
- (GstNetControlMessageMeta *) gst_buffer_add_meta (buffer,
- GST_NET_CONTROL_MESSAGE_META_INFO, NULL);
-
- meta->message = g_object_ref (message);
-
- return meta;
-}
diff --git a/libs/gst/net/gstnetcontrolmessagemeta.h b/libs/gst/net/gstnetcontrolmessagemeta.h
deleted file mode 100644
index b51b87683c..0000000000
--- a/libs/gst/net/gstnetcontrolmessagemeta.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* GStreamer
- * Copyright (C) <2014> William Manley <will@williammanley.net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_NET_CONTROL_MESSAGE_META_H__
-#define __GST_NET_CONTROL_MESSAGE_META_H__
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstNetControlMessageMeta GstNetControlMessageMeta;
-
-/**
- * GstNetControlMessageMeta:
- * @meta: the parent type
- * @message: a #GSocketControlMessage stored as metadata
- *
- * Buffer metadata for GSocket control messages, AKA ancillary data attached to
- * data sent across a socket.
- */
-struct _GstNetControlMessageMeta {
- GstMeta meta;
-
- GSocketControlMessage *message;
-};
-
-GST_NET_API
-GType gst_net_control_message_meta_api_get_type (void);
-
-#define GST_NET_CONTROL_MESSAGE_META_API_TYPE \
- (gst_net_control_message_meta_api_get_type())
-
-#define gst_buffer_get_net_control_message_meta(b) ((GstNetControlMessageMeta*)\
- gst_buffer_get_meta((b),GST_NET_CONTROL_MESSAGE_META_API_TYPE))
-
-/* implementation */
-
-GST_NET_API
-const GstMetaInfo *gst_net_control_message_meta_get_info (void);
-
-#define GST_NET_CONTROL_MESSAGE_META_INFO \
- (gst_net_control_message_meta_get_info())
-
-GST_NET_API
-GstNetControlMessageMeta * gst_buffer_add_net_control_message_meta (GstBuffer * buffer,
- GSocketControlMessage * message);
-
-G_END_DECLS
-
-#endif /* __GST_NET_CONTROL_MESSAGE_META_H__ */
-
diff --git a/libs/gst/net/gstnettimepacket.c b/libs/gst/net/gstnettimepacket.c
deleted file mode 100644
index f914988d31..0000000000
--- a/libs/gst/net/gstnettimepacket.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
- * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
- * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstnettimepacket
- * @title: 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-
-#ifdef __CYGWIN__
-# include <unistd.h>
-# include <fcntl.h>
-#endif
-
-#include "gstnettimepacket.h"
-
-G_DEFINE_BOXED_TYPE (GstNetTimePacket, gst_net_time_packet,
- gst_net_time_packet_copy, gst_net_time_packet_free);
-
-/**
- * gst_net_time_packet_new:
- * @buffer: (array): 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 (gst_net_time_packet_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_free:
- * @packet: the #GstNetTimePacket
- *
- * Free @packet.
- */
-void
-gst_net_time_packet_free (GstNetTimePacket * packet)
-{
- g_free (packet);
-}
-
-/**
- * gst_net_time_packet_copy:
- * @packet: the #GstNetTimePacket
- *
- * Make a copy of @packet.
- *
- * Returns: a copy of @packet, free with gst_net_time_packet_free().
- */
-GstNetTimePacket *
-gst_net_time_packet_copy (const GstNetTimePacket * packet)
-{
- GstNetTimePacket *ret;
-
- ret = g_new0 (GstNetTimePacket, 1);
- ret->local_time = packet->local_time;
- ret->remote_time = packet->remote_time;
-
- 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:
- * @socket: socket to receive the time packet on
- * @src_address: (out): address of variable to return sender address
- * @error: return address for a #GError, or NULL
- *
- * Receives a #GstNetTimePacket over a socket. Handles interrupted system
- * calls, but otherwise returns NULL on error.
- *
- * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free
- * with gst_net_time_packet_free() when done.
- */
-GstNetTimePacket *
-gst_net_time_packet_receive (GSocket * socket,
- GSocketAddress ** src_address, GError ** error)
-{
- gchar buffer[GST_NET_TIME_PACKET_SIZE];
- GError *err = NULL;
- gssize ret;
-
- g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- while (TRUE) {
- ret = g_socket_receive_from (socket, src_address, buffer,
- GST_NET_TIME_PACKET_SIZE, NULL, &err);
-
- if (ret < 0) {
- if (err->code == G_IO_ERROR_WOULD_BLOCK) {
- g_error_free (err);
- err = NULL;
- continue;
- } else {
- goto receive_error;
- }
- } else if (ret < GST_NET_TIME_PACKET_SIZE) {
- goto short_packet;
- } else {
- return gst_net_time_packet_new ((const guint8 *) buffer);
- }
- }
-
-receive_error:
- {
- GST_DEBUG ("receive error: %s", err->message);
- g_propagate_error (error, err);
- return NULL;
- }
-short_packet:
- {
- GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)",
- ret, GST_NET_TIME_PACKET_SIZE);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
- "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE);
- return NULL;
- }
-}
-
-/**
- * gst_net_time_packet_send:
- * @packet: the #GstNetTimePacket to send
- * @socket: socket to send the time packet on
- * @dest_address: address to send the time packet to
- * @error: return address for a #GError, or NULL
- *
- * Sends a #GstNetTimePacket over a socket.
- *
- * MT safe.
- *
- * Returns: TRUE if successful, FALSE in case an error occurred.
- */
-gboolean
-gst_net_time_packet_send (const GstNetTimePacket * packet,
- GSocket * socket, GSocketAddress * dest_address, GError ** error)
-{
- gboolean was_blocking;
- guint8 *buffer;
- gssize res;
-
- g_return_val_if_fail (packet != NULL, FALSE);
- g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
- g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- was_blocking = g_socket_get_blocking (socket);
-
- if (was_blocking)
- g_socket_set_blocking (socket, FALSE);
-
- /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
- buffer = gst_net_time_packet_serialize (packet);
-
- res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
- GST_NET_TIME_PACKET_SIZE, NULL, error);
-
- /* datagram packets should be sent as a whole or not at all */
- g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE);
-
- g_free (buffer);
-
- if (was_blocking)
- g_socket_set_blocking (socket, TRUE);
-
- return (res == GST_NET_TIME_PACKET_SIZE);
-}
diff --git a/libs/gst/net/gstnettimepacket.h b/libs/gst/net/gstnettimepacket.h
deleted file mode 100644
index a8f2f661bd..0000000000
--- a/libs/gst/net/gstnettimepacket.h
+++ /dev/null
@@ -1,81 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NET_TIME_PACKET_H__
-#define __GST_NET_TIME_PACKET_H__
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-/**
- * 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;
-};
-
-GST_NET_API
-GType gst_net_time_packet_get_type (void);
-
-GST_NET_API
-GstNetTimePacket* gst_net_time_packet_new (const guint8 *buffer);
-
-GST_NET_API
-GstNetTimePacket* gst_net_time_packet_copy (const GstNetTimePacket *packet);
-
-GST_NET_API
-void gst_net_time_packet_free (GstNetTimePacket *packet);
-
-GST_NET_API
-guint8* gst_net_time_packet_serialize (const GstNetTimePacket *packet);
-
-GST_NET_API
-GstNetTimePacket* gst_net_time_packet_receive (GSocket * socket,
- GSocketAddress ** src_address,
- GError ** error);
-GST_NET_API
-gboolean gst_net_time_packet_send (const GstNetTimePacket * packet,
- GSocket * socket,
- GSocketAddress * dest_address,
- GError ** error);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimePacket, gst_net_time_packet_free)
-
-G_END_DECLS
-
-
-#endif /* __GST_NET_TIME_PACKET_H__ */
diff --git a/libs/gst/net/gstnettimeprovider.c b/libs/gst/net/gstnettimeprovider.c
deleted file mode 100644
index 1df6959f02..0000000000
--- a/libs/gst/net/gstnettimeprovider.c
+++ /dev/null
@@ -1,477 +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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstnettimeprovider
- * @title: 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 number as arguments.
- *
- * After creating the object, a client clock such as #GstNetClientClock can
- * query the exposed clock over the network for its values.
- *
- * The #GstNetTimeProvider typically wraps the clock used by a #GstPipeline.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstnettimeprovider.h"
-#include "gstnettimepacket.h"
-#include "gstnetutils.h"
-
-GST_DEBUG_CATEGORY_STATIC (ntp_debug);
-#define GST_CAT_DEFAULT (ntp_debug)
-
-#define DEFAULT_ADDRESS "0.0.0.0"
-#define DEFAULT_PORT 5637
-#define DEFAULT_QOS_DSCP -1
-
-#define IS_ACTIVE(self) (g_atomic_int_get (&((self)->priv->active)))
-
-enum
-{
- PROP_0,
- PROP_PORT,
- PROP_ADDRESS,
- PROP_CLOCK,
- PROP_ACTIVE,
- PROP_QOS_DSCP
-};
-
-struct _GstNetTimeProviderPrivate
-{
- gchar *address;
- int port;
- gint qos_dscp; /* ATOMIC */
-
- GThread *thread;
-
- GstClock *clock;
-
- gboolean active; /* ATOMIC */
-
- GSocket *socket;
- GCancellable *cancel;
- gboolean made_cancel_fd;
-};
-
-static void gst_net_time_provider_initable_iface_init (gpointer g_iface);
-
-static gboolean gst_net_time_provider_start (GstNetTimeProvider * bself,
- GError ** error);
-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 \
- GST_DEBUG_CATEGORY_INIT (ntp_debug, "nettime", 0, "Network time provider"); \
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gst_net_time_provider_initable_iface_init)
-
-#define gst_net_time_provider_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstNetTimeProvider, gst_net_time_provider,
- GST_TYPE_OBJECT, G_ADD_PRIVATE (GstNetTimeProvider) _do_init);
-
-static void
-gst_net_time_provider_class_init (GstNetTimeProviderClass * klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- g_assert (sizeof (GstClockTime) == 8);
-
- 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 (gobject_class, 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_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
- 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_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
- 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 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_ACTIVE,
- g_param_spec_boolean ("active", "Active",
- "TRUE if the clock will respond to queries over the network", TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_QOS_DSCP,
- g_param_spec_int ("qos-dscp", "QoS diff srv code point",
- "Quality of Service, differentiated services code point (-1 default)",
- -1, 63, DEFAULT_QOS_DSCP,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gst_net_time_provider_init (GstNetTimeProvider * self)
-{
- self->priv = gst_net_time_provider_get_instance_private (self);
-
- self->priv->port = DEFAULT_PORT;
- self->priv->address = g_strdup (DEFAULT_ADDRESS);
- self->priv->qos_dscp = DEFAULT_QOS_DSCP;
- self->priv->thread = NULL;
- self->priv->active = TRUE;
-}
-
-static void
-gst_net_time_provider_finalize (GObject * object)
-{
- GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
-
- if (self->priv->thread) {
- gst_net_time_provider_stop (self);
- g_assert (self->priv->thread == NULL);
- }
-
- g_free (self->priv->address);
- self->priv->address = NULL;
-
- if (self->priv->clock)
- gst_object_unref (self->priv->clock);
- self->priv->clock = NULL;
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gpointer
-gst_net_time_provider_thread (gpointer data)
-{
- GstNetTimeProvider *self = data;
- GCancellable *cancel = self->priv->cancel;
- GSocket *socket = self->priv->socket;
- GstNetTimePacket *packet;
- GError *err = NULL;
- gint cur_qos_dscp = DEFAULT_QOS_DSCP;
- gint new_qos_dscp;
-
- GST_INFO_OBJECT (self, "time provider thread is running");
-
- while (TRUE) {
- GSocketAddress *sender_addr = NULL;
-
-
- GST_LOG_OBJECT (self, "waiting on socket");
- if (!g_socket_condition_wait (socket, G_IO_IN, cancel, &err)) {
- GST_INFO_OBJECT (self, "socket error: %s", err->message);
-
- if (err->code == G_IO_ERROR_CANCELLED)
- break;
-
- /* try again */
- g_usleep (G_USEC_PER_SEC / 10);
- g_error_free (err);
- err = NULL;
- continue;
- }
-
- /* got data in */
- packet = gst_net_time_packet_receive (socket, &sender_addr, &err);
-
- if (err != NULL) {
- GST_DEBUG_OBJECT (self, "receive error: %s", err->message);
- g_usleep (G_USEC_PER_SEC / 10);
- g_error_free (err);
- err = NULL;
- continue;
- }
-
- /* before next sending check if need to change QoS */
- new_qos_dscp = self->priv->qos_dscp;
- if (cur_qos_dscp != new_qos_dscp &&
- gst_net_utils_set_socket_tos (socket, new_qos_dscp)) {
- GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp);
- cur_qos_dscp = new_qos_dscp;
- }
-
- if (IS_ACTIVE (self)) {
- /* do what we were asked to and send the packet back */
- packet->remote_time = gst_clock_get_time (self->priv->clock);
-
- /* ignore errors */
- gst_net_time_packet_send (packet, socket, sender_addr, NULL);
- g_object_unref (sender_addr);
- g_free (packet);
- }
- }
-
- g_error_free (err);
-
- GST_INFO_OBJECT (self, "time provider thread is stopping");
- 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);
- GstClock **clock_p = &self->priv->clock;
-
- switch (prop_id) {
- case PROP_PORT:
- self->priv->port = g_value_get_int (value);
- break;
- case PROP_ADDRESS:
- g_free (self->priv->address);
- if (g_value_get_string (value) == NULL)
- self->priv->address = g_strdup (DEFAULT_ADDRESS);
- else
- self->priv->address = g_value_dup_string (value);
- break;
- case PROP_CLOCK:
- gst_object_replace ((GstObject **) clock_p,
- (GstObject *) g_value_get_object (value));
- break;
- case PROP_ACTIVE:
- g_atomic_int_set (&self->priv->active, g_value_get_boolean (value));
- break;
- case PROP_QOS_DSCP:
- g_atomic_int_set (&self->priv->qos_dscp, g_value_get_int (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->priv->port);
- break;
- case PROP_ADDRESS:
- g_value_set_string (value, self->priv->address);
- break;
- case PROP_CLOCK:
- g_value_set_object (value, self->priv->clock);
- break;
- case PROP_ACTIVE:
- g_value_set_boolean (value, IS_ACTIVE (self));
- break;
- case PROP_QOS_DSCP:
- g_value_set_int (value, self->priv->qos_dscp);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_net_time_provider_start (GstNetTimeProvider * self, GError ** error)
-{
- GSocketAddress *socket_addr, *bound_addr;
- GInetAddress *inet_addr;
- GPollFD dummy_pollfd;
- GSocket *socket;
- int port;
- gchar *address;
- GError *err = NULL;
-
- if (self->priv->address) {
- inet_addr = g_inet_address_new_from_string (self->priv->address);
- if (inet_addr == NULL) {
- err =
- g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
- "Failed to parse address '%s'", self->priv->address);
- goto invalid_address;
- }
- } else {
- inet_addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
- }
-
- GST_LOG_OBJECT (self, "creating socket");
- socket = g_socket_new (g_inet_address_get_family (inet_addr),
- G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err);
-
- if (!socket)
- goto no_socket;
-
- GST_DEBUG_OBJECT (self, "binding on port %d", self->priv->port);
- socket_addr = g_inet_socket_address_new (inet_addr, self->priv->port);
- if (!g_socket_bind (socket, socket_addr, TRUE, &err)) {
- g_object_unref (socket_addr);
- g_object_unref (inet_addr);
- goto bind_error;
- }
- g_object_unref (socket_addr);
- g_object_unref (inet_addr);
-
- bound_addr = g_socket_get_local_address (socket, NULL);
- port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_addr));
- inet_addr =
- g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (bound_addr));
- address = g_inet_address_to_string (inet_addr);
-
- if (g_strcmp0 (address, self->priv->address)) {
- g_free (self->priv->address);
- self->priv->address = address;
- GST_DEBUG_OBJECT (self, "notifying address %s", address);
- g_object_notify (G_OBJECT (self), "address");
- } else {
- g_free (address);
- }
- if (port != self->priv->port) {
- self->priv->port = port;
- GST_DEBUG_OBJECT (self, "notifying port %d", port);
- g_object_notify (G_OBJECT (self), "port");
- }
- GST_DEBUG_OBJECT (self, "bound on UDP address %s, port %d",
- self->priv->address, port);
- g_object_unref (bound_addr);
-
- self->priv->socket = socket;
- self->priv->cancel = g_cancellable_new ();
- self->priv->made_cancel_fd =
- g_cancellable_make_pollfd (self->priv->cancel, &dummy_pollfd);
-
- self->priv->thread = g_thread_try_new ("GstNetTimeProvider",
- gst_net_time_provider_thread, self, &err);
-
- if (!self->priv->thread)
- goto no_thread;
-
- return TRUE;
-
- /* ERRORS */
-invalid_address:
- {
- GST_ERROR_OBJECT (self, "invalid address: %s", self->priv->address);
- g_propagate_error (error, err);
- return FALSE;
- }
-no_socket:
- {
- GST_ERROR_OBJECT (self, "could not create socket: %s", err->message);
- g_propagate_error (error, err);
- g_object_unref (inet_addr);
- return FALSE;
- }
-bind_error:
- {
- GST_ERROR_OBJECT (self, "bind failed: %s", err->message);
- g_propagate_error (error, err);
- g_object_unref (socket);
- return FALSE;
- }
-no_thread:
- {
- GST_ERROR_OBJECT (self, "could not create thread: %s", err->message);
- g_propagate_error (error, err);
- g_object_unref (self->priv->socket);
- self->priv->socket = NULL;
- g_object_unref (self->priv->cancel);
- self->priv->cancel = NULL;
- return FALSE;
- }
-}
-
-static void
-gst_net_time_provider_stop (GstNetTimeProvider * self)
-{
- g_return_if_fail (self->priv->thread != NULL);
-
- GST_INFO_OBJECT (self, "stopping..");
- g_cancellable_cancel (self->priv->cancel);
-
- g_thread_join (self->priv->thread);
- self->priv->thread = NULL;
-
- if (self->priv->made_cancel_fd)
- g_cancellable_release_fd (self->priv->cancel);
-
- g_object_unref (self->priv->cancel);
- self->priv->cancel = NULL;
-
- g_object_unref (self->priv->socket);
- self->priv->socket = NULL;
-
- GST_INFO_OBJECT (self, "stopped");
-}
-
-static gboolean
-gst_net_time_provider_initable_init (GInitable * initable,
- GCancellable * cancellable, GError ** error)
-{
- GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (initable);
-
- return gst_net_time_provider_start (self, error);
-}
-
-static void
-gst_net_time_provider_initable_iface_init (gpointer g_iface)
-{
- GInitableIface *iface = g_iface;
-
- iface->init = gst_net_time_provider_initable_init;
-}
-
-/**
- * gst_net_time_provider_new:
- * @clock: a #GstClock to export over the network
- * @address: (allow-none): an address to bind on as a dotted quad
- * (xxx.xxx.xxx.xxx), IPv6 address, or NULL to bind to all addresses
- * @port: a port to bind on, or 0 to let the kernel choose
- *
- * Allows network clients to get the current time of @clock.
- *
- * Returns: (transfer full): the new #GstNetTimeProvider, or NULL on error
- */
-GstNetTimeProvider *
-gst_net_time_provider_new (GstClock * clock, const gchar * address, gint port)
-{
- GstNetTimeProvider *ret;
-
- g_return_val_if_fail (clock && GST_IS_CLOCK (clock), NULL);
- g_return_val_if_fail (port >= 0 && port <= G_MAXUINT16, NULL);
-
- ret =
- g_initable_new (GST_TYPE_NET_TIME_PROVIDER, NULL, NULL, "clock", clock,
- "address", address, "port", port, NULL);
-
- /* Clear floating flag */
- g_object_ref_sink (ret);
-
- return ret;
-}
diff --git a/libs/gst/net/gstnettimeprovider.h b/libs/gst/net/gstnettimeprovider.h
deleted file mode 100644
index 40eeef318d..0000000000
--- a/libs/gst/net/gstnettimeprovider.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
- * 2006 Joni Valtanen <joni.valtanen@movial.fi>
- * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NET_TIME_PROVIDER_H__
-#define __GST_NET_TIME_PROVIDER_H__
-
-#include <gst/gst.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-#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,GstNetTimeProviderClass))
-#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(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_TIME_PROVIDER))
-
-typedef struct _GstNetTimeProvider GstNetTimeProvider;
-typedef struct _GstNetTimeProviderClass GstNetTimeProviderClass;
-typedef struct _GstNetTimeProviderPrivate GstNetTimeProviderPrivate;
-
-/**
- * GstNetTimeProvider:
- *
- * Opaque #GstNetTimeProvider structure.
- */
-struct _GstNetTimeProvider {
- GstObject parent;
-
- /*< private >*/
- GstNetTimeProviderPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstNetTimeProviderClass {
- GstObjectClass parent_class;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GST_NET_API
-GType gst_net_time_provider_get_type (void);
-
-GST_NET_API
-GstNetTimeProvider* gst_net_time_provider_new (GstClock *clock,
- const gchar *address,
- gint port);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimeProvider, gst_object_unref)
-
-G_END_DECLS
-
-
-#endif /* __GST_NET_TIME_PROVIDER_H__ */
diff --git a/libs/gst/net/gstnetutils.c b/libs/gst/net/gstnetutils.c
deleted file mode 100644
index 3390e7d65d..0000000000
--- a/libs/gst/net/gstnetutils.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* GStreamer
- * Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
- * Copyright (C) 2017 Robert Rosengren <robertr@axis.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstnetutils
- * @title: GstNetUtils
- * @short_description: Network utility functions.
- *
- * GstNetUtils gathers network utility functions, enabling use for all
- * gstreamer plugins.
- *
- * Since: 1.18
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstnetutils.h"
-#include <gst/gstinfo.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifndef G_OS_WIN32
-#include <netinet/in.h>
-#endif
-
-/**
- * gst_net_utils_set_socket_tos:
- * @socket: Socket to configure
- * @qos_dscp: QoS DSCP value
- *
- * Configures IP_TOS value of socket, i.e. sets QoS DSCP.
- *
- * Returns: TRUE if successful, FALSE in case an error occurred.
- *
- * Since: 1.18
- */
-gboolean
-gst_net_utils_set_socket_tos (GSocket * socket, gint qos_dscp)
-{
- gboolean ret = FALSE;
-
-#ifdef IP_TOS
- gint tos, fd;
- fd = g_socket_get_fd (socket);
-
- /* Extract and shift 6 bits of DSFIELD */
- tos = (qos_dscp & 0x3f) << 2;
-
- if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
- GST_ERROR ("could not set TOS: %s", g_strerror (errno));
- } else {
- ret = TRUE;
- }
-#ifdef IPV6_TCLASS
- if (g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6) {
- if (setsockopt (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0) {
- GST_ERROR ("could not set TCLASS: %s", g_strerror (errno));
- } else {
- ret = TRUE;
- }
- }
-#endif
-#endif
-
- return ret;
-}
diff --git a/libs/gst/net/gstnetutils.h b/libs/gst/net/gstnetutils.h
deleted file mode 100644
index d2b4043be8..0000000000
--- a/libs/gst/net/gstnetutils.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* GStreamer
- * Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
- * Copyright (C) 2017 Robert Rosengren <robertr@axis.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NET_UTILS_H__
-#define __GST_NET_UTILS_H__
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-GST_NET_API
-gboolean gst_net_utils_set_socket_tos (GSocket * socket,
- gint qos_dscp);
-
-G_END_DECLS
-
-#endif /* __GST_NET_UTILS_H__ */
diff --git a/libs/gst/net/gstntppacket.c b/libs/gst/net/gstntppacket.c
deleted file mode 100644
index 8d88d75c12..0000000000
--- a/libs/gst/net/gstntppacket.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
- * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
- * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/* THIS IS A PRIVATE API
- * SECTION:gstntppacket
- * @short_description: Helper structure to construct clock packets used
- * by network clocks for NTPv4.
- * @see_also: #GstClock, #GstNetClientClock, #GstNtpClock
- *
- * Various functions for receiving, sending an serializing #GstNtpPacket
- * structures.
- */
-
-/* FIXME 2.0: Merge this with GstNetTimePacket! */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-
-#ifdef __CYGWIN__
-# include <unistd.h>
-# include <fcntl.h>
-#endif
-
-#include <gst/gst.h>
-#include <string.h>
-
-#include "gstntppacket.h"
-
-G_DEFINE_BOXED_TYPE (GstNtpPacket, gst_ntp_packet,
- gst_ntp_packet_copy, gst_ntp_packet_free);
-
-
-static inline GstClockTime
-ntp_timestamp_to_gst_clock_time (guint32 seconds, guint32 fraction)
-{
- return gst_util_uint64_scale (seconds, GST_SECOND, 1) +
- gst_util_uint64_scale (fraction, GST_SECOND,
- G_GUINT64_CONSTANT (1) << 32);
-}
-
-static inline guint32
-gst_clock_time_to_ntp_timestamp_seconds (GstClockTime gst)
-{
- GstClockTime seconds = gst_util_uint64_scale (gst, 1, GST_SECOND);
-
- return seconds;
-}
-
-static inline guint32
-gst_clock_time_to_ntp_timestamp_fraction (GstClockTime gst)
-{
- GstClockTime seconds = gst_util_uint64_scale (gst, 1, GST_SECOND);
-
- return gst_util_uint64_scale (gst - seconds, G_GUINT64_CONSTANT (1) << 32,
- GST_SECOND);
-}
-
-/**
- * gst_ntp_packet_new:
- * @buffer: (array): a buffer from which to construct the packet, or NULL
- * @error: a #GError
- *
- * Creates a new #GstNtpPacket from a buffer received over the network. The
- * caller is responsible for ensuring that @buffer is at least
- * #GST_NTP_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 (gst_ntp_packet_free to free).
- *
- * Returns: The new #GstNtpPacket.
- */
-GstNtpPacket *
-gst_ntp_packet_new (const guint8 * buffer, GError ** error)
-{
- GstNtpPacket *ret;
-
- g_assert (sizeof (GstClockTime) == 8);
-
- if (buffer) {
- guint8 version = (buffer[0] >> 3) & 0x7;
- guint8 stratum = buffer[1];
- gint8 poll_interval = buffer[2];
-
- if (version != 4) {
- g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_WRONG_VERSION,
- "Invalid NTP version %d", version);
- return NULL;
- }
-
- /* Kiss-o'-Death packet! */
- if (stratum == 0) {
- gchar code[5] = { buffer[3 * 4 + 0], buffer[3 * 4 + 1], buffer[3 * 4 + 2],
- buffer[3 * 4 + 3], 0
- };
-
- /* AUTH, AUTO, CRYP, DENY, RSTR, NKEY => DENY */
- if (strcmp (code, "AUTH") == 0 ||
- strcmp (code, "AUTO") == 0 ||
- strcmp (code, "CRYP") == 0 ||
- strcmp (code, "DENY") == 0 ||
- strcmp (code, "RSTR") == 0 || strcmp (code, "NKEY") == 0) {
- g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_DENY,
- "Kiss-o'-Death denied '%s'", code);
- } else if (strcmp (code, "RATE") == 0) {
- g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_RATE,
- "Kiss-o'-Death '%s'", code);
- } else {
- g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_UNKNOWN,
- "Kiss-o'-Death unknown '%s'", code);
- }
-
- return NULL;
- }
-
- ret = g_new0 (GstNtpPacket, 1);
- ret->origin_time =
- ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 6 * 4),
- GST_READ_UINT32_BE (buffer + 7 * 4));
- ret->receive_time =
- ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 8 * 4),
- GST_READ_UINT32_BE (buffer + 9 * 4));
- ret->transmit_time =
- ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 10 * 4),
- GST_READ_UINT32_BE (buffer + 11 * 4));
-
- /* Wireshark considers everything >= 3 as invalid */
- if (poll_interval >= 3)
- ret->poll_interval = GST_CLOCK_TIME_NONE;
- else if (poll_interval >= 0)
- ret->poll_interval = GST_SECOND << poll_interval;
- else
- ret->poll_interval = GST_SECOND >> (-poll_interval);
- } else {
- ret = g_new0 (GstNtpPacket, 1);
- ret->origin_time = 0;
- ret->receive_time = 0;
- ret->transmit_time = 0;
- ret->poll_interval = 0;
- }
-
- return ret;
-}
-
-/**
- * gst_ntp_packet_free:
- * @packet: the #GstNtpPacket
- *
- * Free @packet.
- */
-void
-gst_ntp_packet_free (GstNtpPacket * packet)
-{
- g_free (packet);
-}
-
-/**
- * gst_ntp_packet_copy:
- * @packet: the #GstNtpPacket
- *
- * Make a copy of @packet.
- *
- * Returns: a copy of @packet, free with gst_ntp_packet_free().
- */
-GstNtpPacket *
-gst_ntp_packet_copy (const GstNtpPacket * packet)
-{
- GstNtpPacket *ret;
-
- ret = g_new0 (GstNtpPacket, 1);
- ret->origin_time = packet->origin_time;
- ret->receive_time = packet->receive_time;
- ret->transmit_time = packet->transmit_time;
-
- return ret;
-}
-
-/**
- * gst_ntp_packet_serialize:
- * @packet: the #GstNtpPacket
- *
- * Serialized a #GstNtpPacket into a newly-allocated sequence of
- * #GST_NTP_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_NTP_PACKET_SIZE bytes.
- */
-guint8 *
-gst_ntp_packet_serialize (const GstNtpPacket * packet)
-{
- guint8 *ret;
-
- g_assert (sizeof (GstClockTime) == 8);
-
- ret = g_new0 (guint8, GST_NTP_PACKET_SIZE);
- /* Leap Indicator: unknown
- * Version: 4
- * Mode: Client
- */
- ret[0] = (3 << 6) | (4 << 3) | (3 << 0);
- /* Stratum: unsynchronized */
- ret[1] = 16;
- /* Polling interval: invalid */
- ret[2] = 3;
- /* Precision: 0 */
- ret[3] = 0;
- /* Root delay: 0 */
- GST_WRITE_UINT32_BE (ret + 4, 0);
- /* Root disperson: 0 */
- GST_WRITE_UINT32_BE (ret + 2 * 4, 0);
- /* Reference ID: \0 */
- GST_WRITE_UINT32_BE (ret + 3 * 4, 0);
- /* Reference Timestamp: 0 */
- GST_WRITE_UINT32_BE (ret + 4 * 4, 0);
- GST_WRITE_UINT32_BE (ret + 5 * 4, 0);
- /* Origin timestamp (local time) */
- GST_WRITE_UINT32_BE (ret + 6 * 4,
- gst_clock_time_to_ntp_timestamp_seconds (packet->origin_time));
- GST_WRITE_UINT32_BE (ret + 7 * 4,
- gst_clock_time_to_ntp_timestamp_fraction (packet->origin_time));
- /* Receive timestamp (remote time) */
- GST_WRITE_UINT32_BE (ret + 8 * 4,
- gst_clock_time_to_ntp_timestamp_seconds (packet->receive_time));
- GST_WRITE_UINT32_BE (ret + 9 * 4,
- gst_clock_time_to_ntp_timestamp_fraction (packet->receive_time));
- /* Transmit timestamp (remote time) */
- GST_WRITE_UINT32_BE (ret + 10 * 4,
- gst_clock_time_to_ntp_timestamp_seconds (packet->transmit_time));
- GST_WRITE_UINT32_BE (ret + 11 * 4,
- gst_clock_time_to_ntp_timestamp_fraction (packet->transmit_time));
-
- return ret;
-}
-
-/**
- * gst_ntp_packet_receive:
- * @socket: socket to receive the time packet on
- * @src_address: (out): address of variable to return sender address
- * @error: return address for a #GError, or NULL
- *
- * Receives a #GstNtpPacket over a socket. Handles interrupted system
- * calls, but otherwise returns NULL on error.
- *
- * Returns: (transfer full): a new #GstNtpPacket, or NULL on error. Free
- * with gst_ntp_packet_free() when done.
- */
-GstNtpPacket *
-gst_ntp_packet_receive (GSocket * socket,
- GSocketAddress ** src_address, GError ** error)
-{
- gchar buffer[GST_NTP_PACKET_SIZE];
- GError *err = NULL;
- gssize ret;
-
- g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- while (TRUE) {
- ret = g_socket_receive_from (socket, src_address, buffer,
- GST_NTP_PACKET_SIZE, NULL, &err);
-
- if (ret < 0) {
- if (err->code == G_IO_ERROR_WOULD_BLOCK) {
- g_error_free (err);
- err = NULL;
- continue;
- } else {
- goto receive_error;
- }
- } else if (ret < GST_NTP_PACKET_SIZE) {
- goto short_packet;
- } else {
- return gst_ntp_packet_new ((const guint8 *) buffer, error);
- }
- }
-
-receive_error:
- {
- GST_DEBUG ("receive error: %s", err->message);
- g_propagate_error (error, err);
- return NULL;
- }
-short_packet:
- {
- GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)",
- ret, GST_NTP_PACKET_SIZE);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
- "short time packet (%d < %d)", (int) ret, GST_NTP_PACKET_SIZE);
- return NULL;
- }
-}
-
-/**
- * gst_ntp_packet_send:
- * @packet: the #GstNtpPacket to send
- * @socket: socket to send the time packet on
- * @dest_address: address to send the time packet to
- * @error: return address for a #GError, or NULL
- *
- * Sends a #GstNtpPacket over a socket.
- *
- * MT safe.
- *
- * Returns: TRUE if successful, FALSE in case an error occurred.
- */
-gboolean
-gst_ntp_packet_send (const GstNtpPacket * packet,
- GSocket * socket, GSocketAddress * dest_address, GError ** error)
-{
- gboolean was_blocking;
- guint8 *buffer;
- gssize res;
-
- g_return_val_if_fail (packet != NULL, FALSE);
- g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
- g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- was_blocking = g_socket_get_blocking (socket);
-
- if (was_blocking)
- g_socket_set_blocking (socket, FALSE);
-
- /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
- buffer = gst_ntp_packet_serialize (packet);
-
- res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
- GST_NTP_PACKET_SIZE, NULL, error);
-
- /* datagram packets should be sent as a whole or not at all */
- g_assert (res < 0 || res == GST_NTP_PACKET_SIZE);
-
- g_free (buffer);
-
- if (was_blocking)
- g_socket_set_blocking (socket, TRUE);
-
- return (res == GST_NTP_PACKET_SIZE);
-}
-
-GQuark
-gst_ntp_error_quark (void)
-{
- static GQuark quark;
-
- /* Thread-safe because GQuark is */
- if (!quark)
- quark = g_quark_from_static_string ("gst-ntp-error-quark");
-
- return quark;
-}
diff --git a/libs/gst/net/gstntppacket.h b/libs/gst/net/gstntppacket.h
deleted file mode 100644
index 0ecd5e881c..0000000000
--- a/libs/gst/net/gstntppacket.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __GST_NTP_PACKET_H__
-#define __GST_NTP_PACKET_H__
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-/**
- * GST_NTP_PACKET_SIZE:
- *
- * The size of the packets sent between NTP clocks.
- */
-#define GST_NTP_PACKET_SIZE 48
-
-typedef struct _GstNtpPacket GstNtpPacket;
-
-/**
- * GstNtpPacket:
- * @origin_time: the time the client packet was sent for the server
- * @receive_time: the time the client packet was received
- * @transmit_time: the time the packet was sent
- * @poll_interval: maximum poll interval
- *
- * Content of a #GstNtpPacket.
- */
-struct _GstNtpPacket {
- GstClockTime origin_time;
- GstClockTime receive_time;
- GstClockTime transmit_time;
-
- GstClockTime poll_interval;
-};
-
-GType gst_ntp_packet_get_type(void) G_GNUC_INTERNAL;
-
-enum {
- GST_NTP_ERROR_WRONG_VERSION,
- GST_NTP_ERROR_KOD_DENY,
- GST_NTP_ERROR_KOD_RATE,
- GST_NTP_ERROR_KOD_UNKNOWN
-};
-
-GQuark gst_ntp_error_quark (void) G_GNUC_INTERNAL;
-#define GST_NTP_ERROR (gst_ntp_error_quark ())
-
-GstNtpPacket* gst_ntp_packet_new (const guint8 *buffer,
- GError ** error) G_GNUC_INTERNAL;
-GstNtpPacket* gst_ntp_packet_copy (const GstNtpPacket *packet) G_GNUC_INTERNAL;
-void gst_ntp_packet_free (GstNtpPacket *packet) G_GNUC_INTERNAL;
-
-guint8* gst_ntp_packet_serialize (const GstNtpPacket *packet) G_GNUC_INTERNAL;
-
-GstNtpPacket* gst_ntp_packet_receive (GSocket * socket,
- GSocketAddress ** src_address,
- GError ** error) G_GNUC_INTERNAL;
-
-gboolean gst_ntp_packet_send (const GstNtpPacket * packet,
- GSocket * socket,
- GSocketAddress * dest_address,
- GError ** error) G_GNUC_INTERNAL;
-
-G_END_DECLS
-
-#endif /* __GST_NET_TIME_PACKET_H__ */
diff --git a/libs/gst/net/gstptp_private.h b/libs/gst/net/gstptp_private.h
deleted file mode 100644
index 18e0e07b35..0000000000
--- a/libs/gst/net/gstptp_private.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __GST_PTP_PRIVATE_H__
-#define __GST_PTP_PRIVATE_H__
-
-#include <glib.h>
-
-enum
-{
- TYPE_EVENT,
- TYPE_GENERAL,
- TYPE_CLOCK_ID
-};
-
-typedef struct
-{
- guint16 size;
- guint8 type;
-} StdIOHeader;
-
-#endif /* __GST_PTP_PRIVATE_H__ */
diff --git a/libs/gst/net/gstptpclock.c b/libs/gst/net/gstptpclock.c
deleted file mode 100644
index 19b90e5969..0000000000
--- a/libs/gst/net/gstptpclock.c
+++ /dev/null
@@ -1,2660 +0,0 @@
-/* GStreamer
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-/**
- * SECTION:gstptpclock
- * @title: GstPtpClock
- * @short_description: Special clock that synchronizes to a remote time
- * provider via PTP (IEEE1588:2008).
- * @see_also: #GstClock, #GstNetClientClock, #GstPipeline
- *
- * GstPtpClock implements a PTP (IEEE1588:2008) ordinary clock in slave-only
- * mode, that allows a GStreamer pipeline to synchronize to a PTP network
- * clock in some specific domain.
- *
- * The PTP subsystem can be initialized with gst_ptp_init(), which then starts
- * a helper process to do the actual communication via the PTP ports. This is
- * required as PTP listens on ports < 1024 and thus requires special
- * privileges. Once this helper process is started, the main process will
- * synchronize to all PTP domains that are detected on the selected
- * interfaces.
- *
- * gst_ptp_clock_new() then allows to create a GstClock that provides the PTP
- * time from a master clock inside a specific PTP domain. This clock will only
- * return valid timestamps once the timestamps in the PTP domain are known. To
- * check this, you can use gst_clock_wait_for_sync(), the GstClock::synced
- * signal and gst_clock_is_synced().
- *
- * To gather statistics about the PTP clock synchronization,
- * gst_ptp_statistics_callback_add() can be used. This gives the application
- * the possibility to collect all kinds of statistics from the clock
- * synchronization.
- *
- * Since: 1.6
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstptpclock.h"
-
-#include "gstptp_private.h"
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef G_OS_WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-#include <sys/types.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#elif defined(G_OS_WIN32)
-#include <io.h>
-#endif
-
-#include <gst/base/base.h>
-
-GST_DEBUG_CATEGORY_STATIC (ptp_debug);
-#define GST_CAT_DEFAULT (ptp_debug)
-
-/* IEEE 1588 7.7.3.1 */
-#define PTP_ANNOUNCE_RECEIPT_TIMEOUT 4
-
-/* Use a running average for calculating the mean path delay instead
- * of just using the last measurement. Enabling this helps in unreliable
- * networks, like wifi, with often changing delays
- *
- * Undef for following IEEE1588-2008 by the letter
- */
-#define USE_RUNNING_AVERAGE_DELAY 1
-
-/* Filter out any measurements that are above a certain threshold compared to
- * previous measurements. Enabling this helps filtering out outliers that
- * happen fairly often in unreliable networks, like wifi.
- *
- * Undef for following IEEE1588-2008 by the letter
- */
-#define USE_MEASUREMENT_FILTERING 1
-
-/* Select the first clock from which we capture a SYNC message as the master
- * clock of the domain until we are ready to run the best master clock
- * algorithm. This allows faster syncing but might mean a change of the master
- * clock in the beginning. As all clocks in a domain are supposed to use the
- * same time, this shouldn't be much of a problem.
- *
- * Undef for following IEEE1588-2008 by the letter
- */
-#define USE_OPPORTUNISTIC_CLOCK_SELECTION 1
-
-/* Only consider SYNC messages for which we are allowed to send a DELAY_REQ
- * afterwards. This allows better synchronization in networks with varying
- * delays, as for every other SYNC message we would have to assume that it's
- * the average of what we saw before. But that might be completely off
- */
-#define USE_ONLY_SYNC_WITH_DELAY 1
-
-/* Filter out delay measurements that are too far away from the median of the
- * last delay measurements, currently those that are more than 2 times as big.
- * This increases accuracy a lot on wifi.
- */
-#define USE_MEDIAN_PRE_FILTERING 1
-#define MEDIAN_PRE_FILTERING_WINDOW 9
-
-/* How many updates should be skipped at maximum when using USE_MEASUREMENT_FILTERING */
-#define MAX_SKIPPED_UPDATES 5
-
-typedef enum
-{
- PTP_MESSAGE_TYPE_SYNC = 0x0,
- PTP_MESSAGE_TYPE_DELAY_REQ = 0x1,
- PTP_MESSAGE_TYPE_PDELAY_REQ = 0x2,
- PTP_MESSAGE_TYPE_PDELAY_RESP = 0x3,
- PTP_MESSAGE_TYPE_FOLLOW_UP = 0x8,
- PTP_MESSAGE_TYPE_DELAY_RESP = 0x9,
- PTP_MESSAGE_TYPE_PDELAY_RESP_FOLLOW_UP = 0xA,
- PTP_MESSAGE_TYPE_ANNOUNCE = 0xB,
- PTP_MESSAGE_TYPE_SIGNALING = 0xC,
- PTP_MESSAGE_TYPE_MANAGEMENT = 0xD
-} PtpMessageType;
-
-typedef struct
-{
- guint64 seconds_field; /* 48 bits valid */
- guint32 nanoseconds_field;
-} PtpTimestamp;
-
-#define PTP_TIMESTAMP_TO_GST_CLOCK_TIME(ptp) (ptp.seconds_field * GST_SECOND + ptp.nanoseconds_field)
-#define GST_CLOCK_TIME_TO_PTP_TIMESTAMP_SECONDS(gst) (((GstClockTime) gst) / GST_SECOND)
-#define GST_CLOCK_TIME_TO_PTP_TIMESTAMP_NANOSECONDS(gst) (((GstClockTime) gst) % GST_SECOND)
-
-typedef struct
-{
- guint64 clock_identity;
- guint16 port_number;
-} PtpClockIdentity;
-
-static gint
-compare_clock_identity (const PtpClockIdentity * a, const PtpClockIdentity * b)
-{
- if (a->clock_identity < b->clock_identity)
- return -1;
- else if (a->clock_identity > b->clock_identity)
- return 1;
-
- if (a->port_number < b->port_number)
- return -1;
- else if (a->port_number > b->port_number)
- return 1;
-
- return 0;
-}
-
-typedef struct
-{
- guint8 clock_class;
- guint8 clock_accuracy;
- guint16 offset_scaled_log_variance;
-} PtpClockQuality;
-
-typedef struct
-{
- guint8 transport_specific;
- PtpMessageType message_type;
- /* guint8 reserved; */
- guint8 version_ptp;
- guint16 message_length;
- guint8 domain_number;
- /* guint8 reserved; */
- guint16 flag_field;
- gint64 correction_field; /* 48.16 fixed point nanoseconds */
- /* guint32 reserved; */
- PtpClockIdentity source_port_identity;
- guint16 sequence_id;
- guint8 control_field;
- gint8 log_message_interval;
-
- union
- {
- struct
- {
- PtpTimestamp origin_timestamp;
- gint16 current_utc_offset;
- /* guint8 reserved; */
- guint8 grandmaster_priority_1;
- PtpClockQuality grandmaster_clock_quality;
- guint8 grandmaster_priority_2;
- guint64 grandmaster_identity;
- guint16 steps_removed;
- guint8 time_source;
- } announce;
-
- struct
- {
- PtpTimestamp origin_timestamp;
- } sync;
-
- struct
- {
- PtpTimestamp precise_origin_timestamp;
- } follow_up;
-
- struct
- {
- PtpTimestamp origin_timestamp;
- } delay_req;
-
- struct
- {
- PtpTimestamp receive_timestamp;
- PtpClockIdentity requesting_port_identity;
- } delay_resp;
-
- } message_specific;
-} PtpMessage;
-
-static GMutex ptp_lock;
-static GCond ptp_cond;
-static gboolean initted = FALSE;
-#ifdef HAVE_PTP
-static gboolean supported = TRUE;
-#else
-static gboolean supported = FALSE;
-#endif
-static GPid ptp_helper_pid;
-static GThread *ptp_helper_thread;
-static GMainContext *main_context;
-static GMainLoop *main_loop;
-static GIOChannel *stdin_channel, *stdout_channel;
-static GRand *delay_req_rand;
-static GstClock *observation_system_clock;
-static PtpClockIdentity ptp_clock_id = { GST_PTP_CLOCK_ID_NONE, 0 };
-
-typedef struct
-{
- GstClockTime receive_time;
-
- PtpClockIdentity master_clock_identity;
-
- guint8 grandmaster_priority_1;
- PtpClockQuality grandmaster_clock_quality;
- guint8 grandmaster_priority_2;
- guint64 grandmaster_identity;
- guint16 steps_removed;
- guint8 time_source;
-
- guint16 sequence_id;
-} PtpAnnounceMessage;
-
-typedef struct
-{
- PtpClockIdentity master_clock_identity;
-
- GstClockTime announce_interval; /* last interval we received */
- GQueue announce_messages;
-} PtpAnnounceSender;
-
-typedef struct
-{
- guint domain;
- PtpClockIdentity master_clock_identity;
-
- guint16 sync_seqnum;
- GstClockTime sync_recv_time_local; /* t2 */
- GstClockTime sync_send_time_remote; /* t1, might be -1 if FOLLOW_UP pending */
- GstClockTime follow_up_recv_time_local;
-
- GSource *timeout_source;
- guint16 delay_req_seqnum;
- GstClockTime delay_req_send_time_local; /* t3, -1 if we wait for FOLLOW_UP */
- GstClockTime delay_req_recv_time_remote; /* t4, -1 if we wait */
- GstClockTime delay_resp_recv_time_local;
-
- gint64 correction_field_sync; /* sum of the correction fields of SYNC/FOLLOW_UP */
- gint64 correction_field_delay; /* sum of the correction fields of DELAY_RESP */
-} PtpPendingSync;
-
-static void
-ptp_pending_sync_free (PtpPendingSync * sync)
-{
- if (sync->timeout_source) {
- g_source_destroy (sync->timeout_source);
- g_source_unref (sync->timeout_source);
- }
- g_free (sync);
-}
-
-typedef struct
-{
- guint domain;
-
- GstClockTime last_ptp_time;
- GstClockTime last_local_time;
- gint skipped_updates;
-
- /* Used for selecting the master/grandmaster */
- GList *announce_senders;
-
- /* Last selected master clock */
- gboolean have_master_clock;
- PtpClockIdentity master_clock_identity;
- guint64 grandmaster_identity;
-
- /* Last SYNC or FOLLOW_UP timestamp we received */
- GstClockTime last_ptp_sync_time;
- GstClockTime sync_interval;
-
- GstClockTime mean_path_delay;
- GstClockTime last_delay_req, min_delay_req_interval;
- guint16 last_delay_req_seqnum;
-
- GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW];
- gint last_path_delays_missing;
-
- GQueue pending_syncs;
-
- GstClock *domain_clock;
-} PtpDomainData;
-
-static GList *domain_data;
-static GMutex domain_clocks_lock;
-static GList *domain_clocks;
-
-/* Protected by PTP lock */
-static void emit_ptp_statistics (guint8 domain, const GstStructure * stats);
-static GHookList domain_stats_hooks;
-static gint domain_stats_n_hooks;
-static gboolean domain_stats_hooks_initted = FALSE;
-
-/* Converts log2 seconds to GstClockTime */
-static GstClockTime
-log2_to_clock_time (gint l)
-{
- if (l < 0)
- return GST_SECOND >> (-l);
- else
- return GST_SECOND << l;
-}
-
-static void
-dump_ptp_message (PtpMessage * msg)
-{
- GST_TRACE ("PTP message:");
- GST_TRACE ("\ttransport_specific: %u", msg->transport_specific);
- GST_TRACE ("\tmessage_type: 0x%01x", msg->message_type);
- GST_TRACE ("\tversion_ptp: %u", msg->version_ptp);
- GST_TRACE ("\tmessage_length: %u", msg->message_length);
- GST_TRACE ("\tdomain_number: %u", msg->domain_number);
- GST_TRACE ("\tflag_field: 0x%04x", msg->flag_field);
- GST_TRACE ("\tcorrection_field: %" G_GINT64_FORMAT ".%03u",
- (msg->correction_field / 65536),
- (guint) ((msg->correction_field & 0xffff) * 1000) / 65536);
- GST_TRACE ("\tsource_port_identity: 0x%016" G_GINT64_MODIFIER "x %u",
- msg->source_port_identity.clock_identity,
- msg->source_port_identity.port_number);
- GST_TRACE ("\tsequence_id: %u", msg->sequence_id);
- GST_TRACE ("\tcontrol_field: 0x%02x", msg->control_field);
- GST_TRACE ("\tmessage_interval: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (log2_to_clock_time (msg->log_message_interval)));
-
- switch (msg->message_type) {
- case PTP_MESSAGE_TYPE_ANNOUNCE:
- GST_TRACE ("\tANNOUNCE:");
- GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u",
- msg->message_specific.announce.origin_timestamp.seconds_field,
- msg->message_specific.announce.origin_timestamp.nanoseconds_field);
- GST_TRACE ("\t\tcurrent_utc_offset: %d",
- msg->message_specific.announce.current_utc_offset);
- GST_TRACE ("\t\tgrandmaster_priority_1: %u",
- msg->message_specific.announce.grandmaster_priority_1);
- GST_TRACE ("\t\tgrandmaster_clock_quality: 0x%02x 0x%02x %u",
- msg->message_specific.announce.grandmaster_clock_quality.clock_class,
- msg->message_specific.announce.
- grandmaster_clock_quality.clock_accuracy,
- msg->message_specific.announce.
- grandmaster_clock_quality.offset_scaled_log_variance);
- GST_TRACE ("\t\tgrandmaster_priority_2: %u",
- msg->message_specific.announce.grandmaster_priority_2);
- GST_TRACE ("\t\tgrandmaster_identity: 0x%016" G_GINT64_MODIFIER "x",
- msg->message_specific.announce.grandmaster_identity);
- GST_TRACE ("\t\tsteps_removed: %u",
- msg->message_specific.announce.steps_removed);
- GST_TRACE ("\t\ttime_source: 0x%02x",
- msg->message_specific.announce.time_source);
- break;
- case PTP_MESSAGE_TYPE_SYNC:
- GST_TRACE ("\tSYNC:");
- GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u",
- msg->message_specific.sync.origin_timestamp.seconds_field,
- msg->message_specific.sync.origin_timestamp.nanoseconds_field);
- break;
- case PTP_MESSAGE_TYPE_FOLLOW_UP:
- GST_TRACE ("\tFOLLOW_UP:");
- GST_TRACE ("\t\tprecise_origin_timestamp: %" G_GUINT64_FORMAT ".%09u",
- msg->message_specific.follow_up.
- precise_origin_timestamp.seconds_field,
- msg->message_specific.follow_up.
- precise_origin_timestamp.nanoseconds_field);
- break;
- case PTP_MESSAGE_TYPE_DELAY_REQ:
- GST_TRACE ("\tDELAY_REQ:");
- GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u",
- msg->message_specific.delay_req.origin_timestamp.seconds_field,
- msg->message_specific.delay_req.origin_timestamp.nanoseconds_field);
- break;
- case PTP_MESSAGE_TYPE_DELAY_RESP:
- GST_TRACE ("\tDELAY_RESP:");
- GST_TRACE ("\t\treceive_timestamp: %" G_GUINT64_FORMAT ".%09u",
- msg->message_specific.delay_resp.receive_timestamp.seconds_field,
- msg->message_specific.delay_resp.receive_timestamp.nanoseconds_field);
- GST_TRACE ("\t\trequesting_port_identity: 0x%016" G_GINT64_MODIFIER
- "x %u",
- msg->message_specific.delay_resp.
- requesting_port_identity.clock_identity,
- msg->message_specific.delay_resp.
- requesting_port_identity.port_number);
- break;
- default:
- break;
- }
- GST_TRACE (" ");
-}
-
-/* IEEE 1588-2008 5.3.3 */
-static gboolean
-parse_ptp_timestamp (PtpTimestamp * timestamp, GstByteReader * reader)
-{
- g_return_val_if_fail (gst_byte_reader_get_remaining (reader) >= 10, FALSE);
-
- timestamp->seconds_field =
- (((guint64) gst_byte_reader_get_uint32_be_unchecked (reader)) << 16) |
- gst_byte_reader_get_uint16_be_unchecked (reader);
- timestamp->nanoseconds_field =
- gst_byte_reader_get_uint32_be_unchecked (reader);
-
- if (timestamp->nanoseconds_field >= 1000000000)
- return FALSE;
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.3 */
-static gboolean
-parse_ptp_message_header (PtpMessage * msg, GstByteReader * reader)
-{
- guint8 b;
-
- g_return_val_if_fail (gst_byte_reader_get_remaining (reader) >= 34, FALSE);
-
- b = gst_byte_reader_get_uint8_unchecked (reader);
- msg->transport_specific = b >> 4;
- msg->message_type = b & 0x0f;
-
- b = gst_byte_reader_get_uint8_unchecked (reader);
- msg->version_ptp = b & 0x0f;
- if (msg->version_ptp != 2) {
- GST_WARNING ("Unsupported PTP message version (%u != 2)", msg->version_ptp);
- return FALSE;
- }
-
- msg->message_length = gst_byte_reader_get_uint16_be_unchecked (reader);
- if (gst_byte_reader_get_remaining (reader) + 4 < msg->message_length) {
- GST_WARNING ("Not enough data (%u < %u)",
- gst_byte_reader_get_remaining (reader) + 4, msg->message_length);
- return FALSE;
- }
-
- msg->domain_number = gst_byte_reader_get_uint8_unchecked (reader);
- gst_byte_reader_skip_unchecked (reader, 1);
-
- msg->flag_field = gst_byte_reader_get_uint16_be_unchecked (reader);
- msg->correction_field = gst_byte_reader_get_uint64_be_unchecked (reader);
- gst_byte_reader_skip_unchecked (reader, 4);
-
- msg->source_port_identity.clock_identity =
- gst_byte_reader_get_uint64_be_unchecked (reader);
- msg->source_port_identity.port_number =
- gst_byte_reader_get_uint16_be_unchecked (reader);
-
- msg->sequence_id = gst_byte_reader_get_uint16_be_unchecked (reader);
- msg->control_field = gst_byte_reader_get_uint8_unchecked (reader);
- msg->log_message_interval = gst_byte_reader_get_uint8_unchecked (reader);
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.5 */
-static gboolean
-parse_ptp_message_announce (PtpMessage * msg, GstByteReader * reader)
-{
- g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_ANNOUNCE, FALSE);
-
- if (gst_byte_reader_get_remaining (reader) < 20)
- return FALSE;
-
- if (!parse_ptp_timestamp (&msg->message_specific.announce.origin_timestamp,
- reader))
- return FALSE;
-
- msg->message_specific.announce.current_utc_offset =
- gst_byte_reader_get_uint16_be_unchecked (reader);
- gst_byte_reader_skip_unchecked (reader, 1);
-
- msg->message_specific.announce.grandmaster_priority_1 =
- gst_byte_reader_get_uint8_unchecked (reader);
- msg->message_specific.announce.grandmaster_clock_quality.clock_class =
- gst_byte_reader_get_uint8_unchecked (reader);
- msg->message_specific.announce.grandmaster_clock_quality.clock_accuracy =
- gst_byte_reader_get_uint8_unchecked (reader);
- msg->message_specific.announce.
- grandmaster_clock_quality.offset_scaled_log_variance =
- gst_byte_reader_get_uint16_be_unchecked (reader);
- msg->message_specific.announce.grandmaster_priority_2 =
- gst_byte_reader_get_uint8_unchecked (reader);
- msg->message_specific.announce.grandmaster_identity =
- gst_byte_reader_get_uint64_be_unchecked (reader);
- msg->message_specific.announce.steps_removed =
- gst_byte_reader_get_uint16_be_unchecked (reader);
- msg->message_specific.announce.time_source =
- gst_byte_reader_get_uint8_unchecked (reader);
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.6 */
-static gboolean
-parse_ptp_message_sync (PtpMessage * msg, GstByteReader * reader)
-{
- g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_SYNC, FALSE);
-
- if (gst_byte_reader_get_remaining (reader) < 10)
- return FALSE;
-
- if (!parse_ptp_timestamp (&msg->message_specific.sync.origin_timestamp,
- reader))
- return FALSE;
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.6 */
-static gboolean
-parse_ptp_message_delay_req (PtpMessage * msg, GstByteReader * reader)
-{
- g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_DELAY_REQ, FALSE);
-
- if (gst_byte_reader_get_remaining (reader) < 10)
- return FALSE;
-
- if (!parse_ptp_timestamp (&msg->message_specific.delay_req.origin_timestamp,
- reader))
- return FALSE;
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.7 */
-static gboolean
-parse_ptp_message_follow_up (PtpMessage * msg, GstByteReader * reader)
-{
- g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_FOLLOW_UP, FALSE);
-
- if (gst_byte_reader_get_remaining (reader) < 10)
- return FALSE;
-
- if (!parse_ptp_timestamp (&msg->message_specific.
- follow_up.precise_origin_timestamp, reader))
- return FALSE;
-
- return TRUE;
-}
-
-/* IEEE 1588-2008 13.8 */
-static gboolean
-parse_ptp_message_delay_resp (PtpMessage * msg, GstByteReader * reader)
-{
- g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_DELAY_RESP,
- FALSE);
-
- if (gst_byte_reader_get_remaining (reader) < 20)
- return FALSE;
-
- if (!parse_ptp_timestamp (&msg->message_specific.delay_resp.receive_timestamp,
- reader))
- return FALSE;
-
- msg->message_specific.delay_resp.requesting_port_identity.clock_identity =
- gst_byte_reader_get_uint64_be_unchecked (reader);
- msg->message_specific.delay_resp.requesting_port_identity.port_number =
- gst_byte_reader_get_uint16_be_unchecked (reader);
-
- return TRUE;
-}
-
-static gboolean
-parse_ptp_message (PtpMessage * msg, const guint8 * data, gsize size)
-{
- GstByteReader reader;
- gboolean ret = FALSE;
-
- gst_byte_reader_init (&reader, data, size);
-
- if (!parse_ptp_message_header (msg, &reader)) {
- GST_WARNING ("Failed to parse PTP message header");
- return FALSE;
- }
-
- switch (msg->message_type) {
- case PTP_MESSAGE_TYPE_SYNC:
- ret = parse_ptp_message_sync (msg, &reader);
- break;
- case PTP_MESSAGE_TYPE_FOLLOW_UP:
- ret = parse_ptp_message_follow_up (msg, &reader);
- break;
- case PTP_MESSAGE_TYPE_DELAY_REQ:
- ret = parse_ptp_message_delay_req (msg, &reader);
- break;
- case PTP_MESSAGE_TYPE_DELAY_RESP:
- ret = parse_ptp_message_delay_resp (msg, &reader);
- break;
- case PTP_MESSAGE_TYPE_ANNOUNCE:
- ret = parse_ptp_message_announce (msg, &reader);
- break;
- default:
- /* ignore for now */
- break;
- }
-
- return ret;
-}
-
-static gint
-compare_announce_message (const PtpAnnounceMessage * a,
- const PtpAnnounceMessage * b)
-{
- /* IEEE 1588 Figure 27 */
- if (a->grandmaster_identity == b->grandmaster_identity) {
- if (a->steps_removed + 1 < b->steps_removed)
- return -1;
- else if (a->steps_removed > b->steps_removed + 1)
- return 1;
-
- /* Error cases are filtered out earlier */
- if (a->steps_removed < b->steps_removed)
- return -1;
- else if (a->steps_removed > b->steps_removed)
- return 1;
-
- /* Error cases are filtered out earlier */
- if (a->master_clock_identity.clock_identity <
- b->master_clock_identity.clock_identity)
- return -1;
- else if (a->master_clock_identity.clock_identity >
- b->master_clock_identity.clock_identity)
- return 1;
-
- /* Error cases are filtered out earlier */
- if (a->master_clock_identity.port_number <
- b->master_clock_identity.port_number)
- return -1;
- else if (a->master_clock_identity.port_number >
- b->master_clock_identity.port_number)
- return 1;
- else
- g_assert_not_reached ();
-
- return 0;
- }
-
- if (a->grandmaster_priority_1 < b->grandmaster_priority_1)
- return -1;
- else if (a->grandmaster_priority_1 > b->grandmaster_priority_1)
- return 1;
-
- if (a->grandmaster_clock_quality.clock_class <
- b->grandmaster_clock_quality.clock_class)
- return -1;
- else if (a->grandmaster_clock_quality.clock_class >
- b->grandmaster_clock_quality.clock_class)
- return 1;
-
- if (a->grandmaster_clock_quality.clock_accuracy <
- b->grandmaster_clock_quality.clock_accuracy)
- return -1;
- else if (a->grandmaster_clock_quality.clock_accuracy >
- b->grandmaster_clock_quality.clock_accuracy)
- return 1;
-
- if (a->grandmaster_clock_quality.offset_scaled_log_variance <
- b->grandmaster_clock_quality.offset_scaled_log_variance)
- return -1;
- else if (a->grandmaster_clock_quality.offset_scaled_log_variance >
- b->grandmaster_clock_quality.offset_scaled_log_variance)
- return 1;
-
- if (a->grandmaster_priority_2 < b->grandmaster_priority_2)
- return -1;
- else if (a->grandmaster_priority_2 > b->grandmaster_priority_2)
- return 1;
-
- if (a->grandmaster_identity < b->grandmaster_identity)
- return -1;
- else if (a->grandmaster_identity > b->grandmaster_identity)
- return 1;
- else
- g_assert_not_reached ();
-
- return 0;
-}
-
-static void
-select_best_master_clock (PtpDomainData * domain, GstClockTime now)
-{
- GList *qualified_messages = NULL;
- GList *l, *m;
- PtpAnnounceMessage *best = NULL;
-
- /* IEEE 1588 9.3.2.5 */
- for (l = domain->announce_senders; l; l = l->next) {
- PtpAnnounceSender *sender = l->data;
- GstClockTime window = 4 * sender->announce_interval;
- gint count = 0;
-
- for (m = sender->announce_messages.head; m; m = m->next) {
- PtpAnnounceMessage *msg = m->data;
-
- if (now - msg->receive_time <= window)
- count++;
- }
-
- /* Only include the newest message of announce senders that had at least 2
- * announce messages in the last 4 announce intervals. Which also means
- * that we wait at least 4 announce intervals before we select a master
- * clock. Until then we just report based on the newest SYNC we received
- */
- if (count >= 2) {
- qualified_messages =
- g_list_prepend (qualified_messages,
- g_queue_peek_tail (&sender->announce_messages));
- }
- }
-
- if (!qualified_messages) {
- GST_DEBUG
- ("No qualified announce messages for domain %u, can't select a master clock",
- domain->domain);
- domain->have_master_clock = FALSE;
- return;
- }
-
- for (l = qualified_messages; l; l = l->next) {
- PtpAnnounceMessage *msg = l->data;
-
- if (!best || compare_announce_message (msg, best) < 0)
- best = msg;
- }
- g_clear_pointer (&qualified_messages, g_list_free);
-
- if (domain->have_master_clock
- && compare_clock_identity (&domain->master_clock_identity,
- &best->master_clock_identity) == 0) {
- GST_DEBUG ("Master clock in domain %u did not change", domain->domain);
- } else {
- GST_DEBUG ("Selected master clock for domain %u: 0x%016" G_GINT64_MODIFIER
- "x %u with grandmaster clock 0x%016" G_GINT64_MODIFIER "x",
- domain->domain, best->master_clock_identity.clock_identity,
- best->master_clock_identity.port_number, best->grandmaster_identity);
-
- domain->have_master_clock = TRUE;
- domain->grandmaster_identity = best->grandmaster_identity;
-
- /* Opportunistic master clock selection likely gave us the same master
- * clock before, no need to reset all statistics */
- if (compare_clock_identity (&domain->master_clock_identity,
- &best->master_clock_identity) != 0) {
- memcpy (&domain->master_clock_identity, &best->master_clock_identity,
- sizeof (PtpClockIdentity));
- domain->mean_path_delay = 0;
- domain->last_delay_req = 0;
- domain->last_path_delays_missing = 9;
- domain->min_delay_req_interval = 0;
- domain->sync_interval = 0;
- domain->last_ptp_sync_time = 0;
- domain->skipped_updates = 0;
- g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free,
- NULL);
- g_queue_clear (&domain->pending_syncs);
- }
-
- if (g_atomic_int_get (&domain_stats_n_hooks)) {
- GstStructure *stats =
- gst_structure_new (GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED,
- "domain", G_TYPE_UINT, domain->domain,
- "master-clock-id", G_TYPE_UINT64,
- domain->master_clock_identity.clock_identity,
- "master-clock-port", G_TYPE_UINT,
- domain->master_clock_identity.port_number,
- "grandmaster-clock-id", G_TYPE_UINT64, domain->grandmaster_identity,
- NULL);
- emit_ptp_statistics (domain->domain, stats);
- gst_structure_free (stats);
- }
- }
-}
-
-static void
-handle_announce_message (PtpMessage * msg, GstClockTime receive_time)
-{
- GList *l;
- PtpDomainData *domain = NULL;
- PtpAnnounceSender *sender = NULL;
- PtpAnnounceMessage *announce;
-
- /* IEEE1588 9.3.2.2 e)
- * Don't consider messages with the alternate master flag set
- */
- if ((msg->flag_field & 0x0100))
- return;
-
- /* IEEE 1588 9.3.2.5 d)
- * Don't consider announce messages with steps_removed>=255
- */
- if (msg->message_specific.announce.steps_removed >= 255)
- return;
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *tmp = l->data;
-
- if (tmp->domain == msg->domain_number) {
- domain = tmp;
- break;
- }
- }
-
- if (!domain) {
- gchar *clock_name;
-
- domain = g_new0 (PtpDomainData, 1);
- domain->domain = msg->domain_number;
- clock_name = g_strdup_printf ("ptp-clock-%u", domain->domain);
- domain->domain_clock =
- g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", clock_name, NULL);
- gst_object_ref_sink (domain->domain_clock);
- g_free (clock_name);
- g_queue_init (&domain->pending_syncs);
- domain->last_path_delays_missing = 9;
- domain_data = g_list_prepend (domain_data, domain);
-
- g_mutex_lock (&domain_clocks_lock);
- domain_clocks = g_list_prepend (domain_clocks, domain);
- g_mutex_unlock (&domain_clocks_lock);
-
- if (g_atomic_int_get (&domain_stats_n_hooks)) {
- GstStructure *stats =
- gst_structure_new (GST_PTP_STATISTICS_NEW_DOMAIN_FOUND, "domain",
- G_TYPE_UINT, domain->domain, "clock", GST_TYPE_CLOCK,
- domain->domain_clock, NULL);
- emit_ptp_statistics (domain->domain, stats);
- gst_structure_free (stats);
- }
- }
-
- for (l = domain->announce_senders; l; l = l->next) {
- PtpAnnounceSender *tmp = l->data;
-
- if (compare_clock_identity (&tmp->master_clock_identity,
- &msg->source_port_identity) == 0) {
- sender = tmp;
- break;
- }
- }
-
- if (!sender) {
- sender = g_new0 (PtpAnnounceSender, 1);
-
- memcpy (&sender->master_clock_identity, &msg->source_port_identity,
- sizeof (PtpClockIdentity));
- g_queue_init (&sender->announce_messages);
- domain->announce_senders =
- g_list_prepend (domain->announce_senders, sender);
- }
-
- for (l = sender->announce_messages.head; l; l = l->next) {
- PtpAnnounceMessage *tmp = l->data;
-
- /* IEEE 1588 9.3.2.5 c)
- * Don't consider identical messages, i.e. duplicates
- */
- if (tmp->sequence_id == msg->sequence_id)
- return;
- }
-
- sender->announce_interval = log2_to_clock_time (msg->log_message_interval);
-
- announce = g_new0 (PtpAnnounceMessage, 1);
- announce->receive_time = receive_time;
- announce->sequence_id = msg->sequence_id;
- memcpy (&announce->master_clock_identity, &msg->source_port_identity,
- sizeof (PtpClockIdentity));
- announce->grandmaster_identity =
- msg->message_specific.announce.grandmaster_identity;
- announce->grandmaster_priority_1 =
- msg->message_specific.announce.grandmaster_priority_1;
- announce->grandmaster_clock_quality.clock_class =
- msg->message_specific.announce.grandmaster_clock_quality.clock_class;
- announce->grandmaster_clock_quality.clock_accuracy =
- msg->message_specific.announce.grandmaster_clock_quality.clock_accuracy;
- announce->grandmaster_clock_quality.offset_scaled_log_variance =
- msg->message_specific.announce.
- grandmaster_clock_quality.offset_scaled_log_variance;
- announce->grandmaster_priority_2 =
- msg->message_specific.announce.grandmaster_priority_2;
- announce->steps_removed = msg->message_specific.announce.steps_removed;
- announce->time_source = msg->message_specific.announce.time_source;
- g_queue_push_tail (&sender->announce_messages, announce);
-
- select_best_master_clock (domain, receive_time);
-}
-
-static gboolean
-send_delay_req_timeout (PtpPendingSync * sync)
-{
- StdIOHeader header = { 0, };
- guint8 delay_req[44];
- GstByteWriter writer;
- GIOStatus status;
- gsize written;
- GError *err = NULL;
-
- header.type = TYPE_EVENT;
- header.size = 44;
-
- GST_TRACE ("Sending delay_req to domain %u", sync->domain);
-
- gst_byte_writer_init_with_data (&writer, delay_req, 44, FALSE);
- gst_byte_writer_put_uint8_unchecked (&writer, PTP_MESSAGE_TYPE_DELAY_REQ);
- gst_byte_writer_put_uint8_unchecked (&writer, 2);
- gst_byte_writer_put_uint16_be_unchecked (&writer, 44);
- gst_byte_writer_put_uint8_unchecked (&writer, sync->domain);
- gst_byte_writer_put_uint8_unchecked (&writer, 0);
- gst_byte_writer_put_uint16_be_unchecked (&writer, 0);
- gst_byte_writer_put_uint64_be_unchecked (&writer, 0);
- gst_byte_writer_put_uint32_be_unchecked (&writer, 0);
- gst_byte_writer_put_uint64_be_unchecked (&writer,
- ptp_clock_id.clock_identity);
- gst_byte_writer_put_uint16_be_unchecked (&writer, ptp_clock_id.port_number);
- gst_byte_writer_put_uint16_be_unchecked (&writer, sync->delay_req_seqnum);
- gst_byte_writer_put_uint8_unchecked (&writer, 0x01);
- gst_byte_writer_put_uint8_unchecked (&writer, 0x7f);
- gst_byte_writer_put_uint64_be_unchecked (&writer, 0);
- gst_byte_writer_put_uint16_be_unchecked (&writer, 0);
-
- status =
- g_io_channel_write_chars (stdout_channel, (gchar *) & header,
- sizeof (header), &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_warning ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- return G_SOURCE_REMOVE;
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status != G_IO_STATUS_NORMAL) {
- g_warning ("Unexpected stdout write status: %d", status);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (written != sizeof (header)) {
- g_warning ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
-
- sync->delay_req_send_time_local =
- gst_clock_get_time (observation_system_clock);
-
- status =
- g_io_channel_write_chars (stdout_channel,
- (const gchar *) delay_req, 44, &written, &err);
- if (status == G_IO_STATUS_ERROR) {
- g_warning ("Failed to write to stdout: %s", err->message);
- g_clear_error (&err);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status == G_IO_STATUS_EOF) {
- g_message ("EOF on stdout");
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status != G_IO_STATUS_NORMAL) {
- g_warning ("Unexpected stdout write status: %d", status);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (written != 44) {
- g_warning ("Unexpected write size: %" G_GSIZE_FORMAT, written);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-send_delay_req (PtpDomainData * domain, PtpPendingSync * sync)
-{
- GstClockTime now = gst_clock_get_time (observation_system_clock);
- guint timeout;
- GSource *timeout_source;
-
- if (domain->last_delay_req != 0
- && domain->last_delay_req + domain->min_delay_req_interval > now) {
- GST_TRACE ("Too soon to send new DELAY_REQ");
- return FALSE;
- }
-
- domain->last_delay_req = now;
- sync->delay_req_seqnum = domain->last_delay_req_seqnum++;
-
- /* IEEE 1588 9.5.11.2 */
- if (domain->last_delay_req == 0 || domain->min_delay_req_interval == 0)
- timeout = 0;
- else
- timeout =
- g_rand_int_range (delay_req_rand, 0,
- (domain->min_delay_req_interval * 2) / GST_MSECOND);
-
- sync->timeout_source = timeout_source = g_timeout_source_new (timeout);
- g_source_set_priority (timeout_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (timeout_source, (GSourceFunc) send_delay_req_timeout,
- sync, NULL);
- g_source_attach (timeout_source, main_context);
-
- return TRUE;
-}
-
-/* Filtering of outliers for RTT and time calculations inspired
- * by the code from gstnetclientclock.c
- */
-static void
-update_ptp_time (PtpDomainData * domain, PtpPendingSync * sync)
-{
- GstClockTime internal_time, external_time, rate_num, rate_den;
- GstClockTime corrected_ptp_time, corrected_local_time;
- gdouble r_squared = 0.0;
- gboolean synced;
- GstClockTimeDiff discont = 0;
- GstClockTime estimated_ptp_time = GST_CLOCK_TIME_NONE;
-#ifdef USE_MEASUREMENT_FILTERING
- GstClockTime orig_internal_time, orig_external_time, orig_rate_num,
- orig_rate_den;
- GstClockTime new_estimated_ptp_time;
- GstClockTime max_discont, estimated_ptp_time_min, estimated_ptp_time_max;
- gboolean now_synced;
-#endif
-#ifdef USE_ONLY_SYNC_WITH_DELAY
- GstClockTime mean_path_delay;
-#endif
-
- GST_TRACE ("Updating PTP time");
-
-#ifdef USE_ONLY_SYNC_WITH_DELAY
- if (sync->delay_req_send_time_local == GST_CLOCK_TIME_NONE) {
- GST_TRACE ("Not updating - no delay_req sent");
- return;
- }
-
- /* IEEE 1588 11.3 */
- mean_path_delay =
- (sync->delay_req_recv_time_remote - sync->sync_send_time_remote +
- sync->sync_recv_time_local - sync->delay_req_send_time_local -
- (sync->correction_field_sync + sync->correction_field_delay +
- 32768) / 65536) / 2;
-#endif
-
- /* IEEE 1588 11.2 */
- corrected_ptp_time =
- sync->sync_send_time_remote +
- (sync->correction_field_sync + 32768) / 65536;
-
-#ifdef USE_ONLY_SYNC_WITH_DELAY
- corrected_local_time = sync->sync_recv_time_local - mean_path_delay;
-#else
- corrected_local_time = sync->sync_recv_time_local - domain->mean_path_delay;
-#endif
-
-#ifdef USE_MEASUREMENT_FILTERING
- /* We check this here and when updating the mean path delay, because
- * we can get here without a delay response too. The tolerance on
- * accepting follow-up after a sync is high, because a PTP server
- * doesn't have to prioritise sending FOLLOW_UP - its purpose is
- * just to give us the accurate timestamp of the preceding SYNC */
- if (sync->follow_up_recv_time_local != GST_CLOCK_TIME_NONE
- && sync->follow_up_recv_time_local >
- sync->sync_recv_time_local + 20 * domain->mean_path_delay) {
- GstClockTimeDiff delay =
- sync->follow_up_recv_time_local - sync->sync_recv_time_local;
- GST_WARNING ("Sync-follow-up delay for domain %u too big: %"
- GST_STIME_FORMAT " > 20 * %" GST_TIME_FORMAT, domain->domain,
- GST_STIME_ARGS (delay), GST_TIME_ARGS (domain->mean_path_delay));
- synced = FALSE;
- gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock),
- &internal_time, &external_time, &rate_num, &rate_den);
- goto out;
- }
-#endif
-
- /* Set an initial local-remote relation */
- if (domain->last_ptp_time == 0)
- gst_clock_set_calibration (domain->domain_clock, corrected_local_time,
- corrected_ptp_time, 1, 1);
-
-#ifdef USE_MEASUREMENT_FILTERING
- /* Check if the corrected PTP time is +/- 3/4 RTT around what we would
- * estimate with our present knowledge about the clock
- */
- /* Store what the clock produced as 'now' before this update */
- gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock),
- &orig_internal_time, &orig_external_time, &orig_rate_num, &orig_rate_den);
- internal_time = orig_internal_time;
- external_time = orig_external_time;
- rate_num = orig_rate_num;
- rate_den = orig_rate_den;
-
- /* 3/4 RTT window around the estimation */
- max_discont = domain->mean_path_delay * 3 / 2;
-
- /* Check if the estimated sync time is inside our window */
- estimated_ptp_time_min = corrected_local_time - max_discont;
- estimated_ptp_time_min =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (domain->domain_clock),
- estimated_ptp_time_min, internal_time, external_time, rate_num, rate_den);
- estimated_ptp_time_max = corrected_local_time + max_discont;
- estimated_ptp_time_max =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST (domain->domain_clock),
- estimated_ptp_time_max, internal_time, external_time, rate_num, rate_den);
-
- synced = (estimated_ptp_time_min < corrected_ptp_time
- && corrected_ptp_time < estimated_ptp_time_max);
-
- GST_DEBUG ("Adding observation for domain %u: %" GST_TIME_FORMAT " - %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (corrected_ptp_time), GST_TIME_ARGS (corrected_local_time));
-
- GST_DEBUG ("Synced %d: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT " < %"
- GST_TIME_FORMAT, synced, GST_TIME_ARGS (estimated_ptp_time_min),
- GST_TIME_ARGS (corrected_ptp_time),
- GST_TIME_ARGS (estimated_ptp_time_max));
-
- if (gst_clock_add_observation_unapplied (domain->domain_clock,
- corrected_local_time, corrected_ptp_time, &r_squared,
- &internal_time, &external_time, &rate_num, &rate_den)) {
- GST_DEBUG ("Regression gave r_squared: %f", r_squared);
-
- /* Old estimated PTP time based on receive time and path delay */
- estimated_ptp_time = corrected_local_time;
- estimated_ptp_time =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST
- (domain->domain_clock), estimated_ptp_time, orig_internal_time,
- orig_external_time, orig_rate_num, orig_rate_den);
-
- /* New estimated PTP time based on receive time and path delay */
- new_estimated_ptp_time = corrected_local_time;
- new_estimated_ptp_time =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST
- (domain->domain_clock), new_estimated_ptp_time, internal_time,
- external_time, rate_num, rate_den);
-
- discont = GST_CLOCK_DIFF (estimated_ptp_time, new_estimated_ptp_time);
- if (synced && ABS (discont) > max_discont) {
- GstClockTimeDiff offset;
- GST_DEBUG ("Too large a discont %s%" GST_TIME_FORMAT
- ", clamping to 1/4 average RTT = %" GST_TIME_FORMAT,
- (discont < 0 ? "-" : ""), GST_TIME_ARGS (ABS (discont)),
- GST_TIME_ARGS (max_discont));
- if (discont > 0) { /* Too large a forward step - add a -ve offset */
- offset = max_discont - discont;
- if (-offset > external_time)
- external_time = 0;
- else
- external_time += offset;
- } else { /* Too large a backward step - add a +ve offset */
- offset = -(max_discont + discont);
- external_time += offset;
- }
-
- discont += offset;
- } else {
- GST_DEBUG ("Discont %s%" GST_TIME_FORMAT " (max: %" GST_TIME_FORMAT ")",
- (discont < 0 ? "-" : ""), GST_TIME_ARGS (ABS (discont)),
- GST_TIME_ARGS (max_discont));
- }
-
- /* Check if the estimated sync time is now (still) inside our window */
- estimated_ptp_time_min = corrected_local_time - max_discont;
- estimated_ptp_time_min =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST
- (domain->domain_clock), estimated_ptp_time_min, internal_time,
- external_time, rate_num, rate_den);
- estimated_ptp_time_max = corrected_local_time + max_discont;
- estimated_ptp_time_max =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST
- (domain->domain_clock), estimated_ptp_time_max, internal_time,
- external_time, rate_num, rate_den);
-
- now_synced = (estimated_ptp_time_min < corrected_ptp_time
- && corrected_ptp_time < estimated_ptp_time_max);
-
- GST_DEBUG ("Now synced %d: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT " < %"
- GST_TIME_FORMAT, now_synced, GST_TIME_ARGS (estimated_ptp_time_min),
- GST_TIME_ARGS (corrected_ptp_time),
- GST_TIME_ARGS (estimated_ptp_time_max));
-
- if (synced || now_synced || domain->skipped_updates > MAX_SKIPPED_UPDATES) {
- gst_clock_set_calibration (GST_CLOCK_CAST (domain->domain_clock),
- internal_time, external_time, rate_num, rate_den);
- domain->skipped_updates = 0;
-
- domain->last_ptp_time = corrected_ptp_time;
- domain->last_local_time = corrected_local_time;
- } else {
- domain->skipped_updates++;
- }
- } else {
- domain->last_ptp_time = corrected_ptp_time;
- domain->last_local_time = corrected_local_time;
- }
-
-#else
- GST_DEBUG ("Adding observation for domain %u: %" GST_TIME_FORMAT " - %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (corrected_ptp_time), GST_TIME_ARGS (corrected_local_time));
-
- gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock),
- &internal_time, &external_time, &rate_num, &rate_den);
-
- estimated_ptp_time = corrected_local_time;
- estimated_ptp_time =
- gst_clock_adjust_with_calibration (GST_CLOCK_CAST
- (domain->domain_clock), estimated_ptp_time, internal_time,
- external_time, rate_num, rate_den);
-
- gst_clock_add_observation (domain->domain_clock,
- corrected_local_time, corrected_ptp_time, &r_squared);
-
- gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock),
- &internal_time, &external_time, &rate_num, &rate_den);
-
- synced = TRUE;
- domain->last_ptp_time = corrected_ptp_time;
- domain->last_local_time = corrected_local_time;
-#endif
-
-#ifdef USE_MEASUREMENT_FILTERING
-out:
-#endif
- if (g_atomic_int_get (&domain_stats_n_hooks)) {
- GstStructure *stats = gst_structure_new (GST_PTP_STATISTICS_TIME_UPDATED,
- "domain", G_TYPE_UINT, domain->domain,
- "mean-path-delay-avg", GST_TYPE_CLOCK_TIME, domain->mean_path_delay,
- "local-time", GST_TYPE_CLOCK_TIME, corrected_local_time,
- "ptp-time", GST_TYPE_CLOCK_TIME, corrected_ptp_time,
- "estimated-ptp-time", GST_TYPE_CLOCK_TIME, estimated_ptp_time,
- "discontinuity", G_TYPE_INT64, discont,
- "synced", G_TYPE_BOOLEAN, synced,
- "r-squared", G_TYPE_DOUBLE, r_squared,
- "internal-time", GST_TYPE_CLOCK_TIME, internal_time,
- "external-time", GST_TYPE_CLOCK_TIME, external_time,
- "rate-num", G_TYPE_UINT64, rate_num,
- "rate-den", G_TYPE_UINT64, rate_den,
- "rate", G_TYPE_DOUBLE, (gdouble) (rate_num) / rate_den,
- NULL);
- emit_ptp_statistics (domain->domain, stats);
- gst_structure_free (stats);
- }
-
-}
-
-#ifdef USE_MEDIAN_PRE_FILTERING
-static gint
-compare_clock_time (const GstClockTime * a, const GstClockTime * b)
-{
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- return 0;
-}
-#endif
-
-static gboolean
-update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync)
-{
-#ifdef USE_MEDIAN_PRE_FILTERING
- GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW];
- GstClockTime median;
- gint i;
-#endif
-
- GstClockTime mean_path_delay, delay_req_delay = 0;
- gboolean ret;
-
- /* IEEE 1588 11.3 */
- mean_path_delay =
- (sync->delay_req_recv_time_remote - sync->sync_send_time_remote +
- sync->sync_recv_time_local - sync->delay_req_send_time_local -
- (sync->correction_field_sync + sync->correction_field_delay +
- 32768) / 65536) / 2;
-
-#ifdef USE_MEDIAN_PRE_FILTERING
- for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++)
- domain->last_path_delays[i - 1] = domain->last_path_delays[i];
- domain->last_path_delays[i - 1] = mean_path_delay;
-
- if (domain->last_path_delays_missing) {
- domain->last_path_delays_missing--;
- } else {
- memcpy (&last_path_delays, &domain->last_path_delays,
- sizeof (last_path_delays));
- g_qsort_with_data (&last_path_delays,
- MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime),
- (GCompareDataFunc) compare_clock_time, NULL);
-
- median = last_path_delays[MEDIAN_PRE_FILTERING_WINDOW / 2];
-
- /* FIXME: We might want to use something else here, like only allowing
- * things in the interquartile range, or also filtering away delays that
- * are too small compared to the median. This here worked well enough
- * in tests so far.
- */
- if (mean_path_delay > 2 * median) {
- GST_WARNING ("Path delay for domain %u too big compared to median: %"
- GST_TIME_FORMAT " > 2 * %" GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (mean_path_delay), GST_TIME_ARGS (median));
- ret = FALSE;
- goto out;
- }
- }
-#endif
-
-#ifdef USE_RUNNING_AVERAGE_DELAY
- /* Track an average round trip time, for a bit of smoothing */
- /* Always update before discarding a sample, so genuine changes in
- * the network get picked up, eventually */
- if (domain->mean_path_delay == 0)
- domain->mean_path_delay = mean_path_delay;
- else if (mean_path_delay < domain->mean_path_delay) /* Shorter RTTs carry more weight than longer */
- domain->mean_path_delay =
- (3 * domain->mean_path_delay + mean_path_delay) / 4;
- else
- domain->mean_path_delay =
- (15 * domain->mean_path_delay + mean_path_delay) / 16;
-#else
- domain->mean_path_delay = mean_path_delay;
-#endif
-
-#ifdef USE_MEASUREMENT_FILTERING
- /* The tolerance on accepting follow-up after a sync is high, because
- * a PTP server doesn't have to prioritise sending FOLLOW_UP - its purpose is
- * just to give us the accurate timestamp of the preceding SYNC */
- if (sync->follow_up_recv_time_local != GST_CLOCK_TIME_NONE &&
- domain->mean_path_delay != 0
- && sync->follow_up_recv_time_local >
- sync->sync_recv_time_local + 20 * domain->mean_path_delay) {
- GST_WARNING ("Sync-follow-up delay for domain %u too big: %" GST_TIME_FORMAT
- " > 20 * %" GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (sync->follow_up_recv_time_local -
- sync->sync_recv_time_local),
- GST_TIME_ARGS (domain->mean_path_delay));
- ret = FALSE;
- goto out;
- }
-
- if (mean_path_delay > 2 * domain->mean_path_delay) {
- GST_WARNING ("Mean path delay for domain %u too big: %" GST_TIME_FORMAT
- " > 2 * %" GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (mean_path_delay),
- GST_TIME_ARGS (domain->mean_path_delay));
- ret = FALSE;
- goto out;
- }
-#endif
-
- delay_req_delay =
- sync->delay_resp_recv_time_local - sync->delay_req_send_time_local;
-
-#ifdef USE_MEASUREMENT_FILTERING
- /* delay_req_delay is a RTT, so 2 times the path delay is what we'd
- * hope for, but some PTP systems don't prioritise sending DELAY_RESP,
- * but they must still have placed an accurate reception timestamp.
- * That means we should be quite tolerant about late DELAY_RESP, and
- * mostly rely on filtering out jumps in the mean-path-delay elsewhere */
- if (delay_req_delay > 20 * domain->mean_path_delay) {
- GST_WARNING ("Delay-request-response delay for domain %u too big: %"
- GST_TIME_FORMAT " > 20 * %" GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (delay_req_delay),
- GST_TIME_ARGS (domain->mean_path_delay));
- ret = FALSE;
- goto out;
- }
-#endif
-
- ret = TRUE;
-
- GST_DEBUG ("Got mean path delay for domain %u: %" GST_TIME_FORMAT " (new: %"
- GST_TIME_FORMAT ")", domain->domain,
- GST_TIME_ARGS (domain->mean_path_delay), GST_TIME_ARGS (mean_path_delay));
- GST_DEBUG ("Delay request delay for domain %u: %" GST_TIME_FORMAT,
- domain->domain, GST_TIME_ARGS (delay_req_delay));
-
-#if defined(USE_MEASUREMENT_FILTERING) || defined(USE_MEDIAN_PRE_FILTERING)
-out:
-#endif
- if (g_atomic_int_get (&domain_stats_n_hooks)) {
- GstStructure *stats =
- gst_structure_new (GST_PTP_STATISTICS_PATH_DELAY_MEASURED,
- "domain", G_TYPE_UINT, domain->domain,
- "mean-path-delay-avg", GST_TYPE_CLOCK_TIME, domain->mean_path_delay,
- "mean-path-delay", GST_TYPE_CLOCK_TIME, mean_path_delay,
- "delay-request-delay", GST_TYPE_CLOCK_TIME, delay_req_delay, NULL);
- emit_ptp_statistics (domain->domain, stats);
- gst_structure_free (stats);
- }
-
- return ret;
-}
-
-static void
-handle_sync_message (PtpMessage * msg, GstClockTime receive_time)
-{
- GList *l;
- PtpDomainData *domain = NULL;
- PtpPendingSync *sync = NULL;
-
- /* Don't consider messages with the alternate master flag set */
- if ((msg->flag_field & 0x0100)) {
- GST_TRACE ("Ignoring sync message with alternate-master flag");
- return;
- }
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *tmp = l->data;
-
- if (msg->domain_number == tmp->domain) {
- domain = tmp;
- break;
- }
- }
-
- if (!domain) {
- gchar *clock_name;
-
- domain = g_new0 (PtpDomainData, 1);
- domain->domain = msg->domain_number;
- clock_name = g_strdup_printf ("ptp-clock-%u", domain->domain);
- domain->domain_clock =
- g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", clock_name, NULL);
- gst_object_ref_sink (domain->domain_clock);
- g_free (clock_name);
- g_queue_init (&domain->pending_syncs);
- domain->last_path_delays_missing = 9;
- domain_data = g_list_prepend (domain_data, domain);
-
- g_mutex_lock (&domain_clocks_lock);
- domain_clocks = g_list_prepend (domain_clocks, domain);
- g_mutex_unlock (&domain_clocks_lock);
- }
-
- /* If we have a master clock, ignore this message if it's not coming from there */
- if (domain->have_master_clock
- && compare_clock_identity (&domain->master_clock_identity,
- &msg->source_port_identity) != 0)
- return;
-
-#ifdef USE_OPPORTUNISTIC_CLOCK_SELECTION
- /* Opportunistic selection of master clock */
- if (!domain->have_master_clock)
- memcpy (&domain->master_clock_identity, &msg->source_port_identity,
- sizeof (PtpClockIdentity));
-#else
- if (!domain->have_master_clock)
- return;
-#endif
-
- domain->sync_interval = log2_to_clock_time (msg->log_message_interval);
-
- /* Check if duplicated */
- for (l = domain->pending_syncs.head; l; l = l->next) {
- PtpPendingSync *tmp = l->data;
-
- if (tmp->sync_seqnum == msg->sequence_id)
- return;
- }
-
- if (msg->message_specific.sync.origin_timestamp.seconds_field >
- GST_CLOCK_TIME_NONE / GST_SECOND) {
- GST_FIXME ("Unsupported sync message seconds field value: %"
- G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT,
- msg->message_specific.sync.origin_timestamp.seconds_field,
- GST_CLOCK_TIME_NONE / GST_SECOND);
- return;
- }
-
- sync = g_new0 (PtpPendingSync, 1);
- sync->domain = domain->domain;
- sync->sync_seqnum = msg->sequence_id;
- sync->sync_recv_time_local = receive_time;
- sync->sync_send_time_remote = GST_CLOCK_TIME_NONE;
- sync->follow_up_recv_time_local = GST_CLOCK_TIME_NONE;
- sync->delay_req_send_time_local = GST_CLOCK_TIME_NONE;
- sync->delay_req_recv_time_remote = GST_CLOCK_TIME_NONE;
- sync->delay_resp_recv_time_local = GST_CLOCK_TIME_NONE;
-
- /* 0.5 correction factor for division later */
- sync->correction_field_sync = msg->correction_field;
-
- if ((msg->flag_field & 0x0200)) {
- /* Wait for FOLLOW_UP */
- GST_TRACE ("Waiting for FOLLOW_UP msg");
- } else {
- sync->sync_send_time_remote =
- PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific.
- sync.origin_timestamp);
-
- if (domain->last_ptp_sync_time != 0
- && domain->last_ptp_sync_time >= sync->sync_send_time_remote) {
- GST_WARNING ("Backwards PTP times in domain %u: %" GST_TIME_FORMAT " >= %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (domain->last_ptp_sync_time),
- GST_TIME_ARGS (sync->sync_send_time_remote));
- ptp_pending_sync_free (sync);
- sync = NULL;
- return;
- }
- domain->last_ptp_sync_time = sync->sync_send_time_remote;
-
- if (send_delay_req (domain, sync)) {
- /* Sent delay request */
- } else {
- update_ptp_time (domain, sync);
- ptp_pending_sync_free (sync);
- sync = NULL;
- }
- }
-
- if (sync)
- g_queue_push_tail (&domain->pending_syncs, sync);
-}
-
-static void
-handle_follow_up_message (PtpMessage * msg, GstClockTime receive_time)
-{
- GList *l;
- PtpDomainData *domain = NULL;
- PtpPendingSync *sync = NULL;
-
- GST_TRACE ("Processing FOLLOW_UP message");
-
- /* Don't consider messages with the alternate master flag set */
- if ((msg->flag_field & 0x0100)) {
- GST_TRACE ("Ignoring FOLLOW_UP with alternate-master flag");
- return;
- }
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *tmp = l->data;
-
- if (msg->domain_number == tmp->domain) {
- domain = tmp;
- break;
- }
- }
-
- if (!domain) {
- GST_TRACE ("No domain match for FOLLOW_UP msg");
- return;
- }
-
- /* If we have a master clock, ignore this message if it's not coming from there */
- if (domain->have_master_clock
- && compare_clock_identity (&domain->master_clock_identity,
- &msg->source_port_identity) != 0) {
- GST_TRACE ("FOLLOW_UP msg not from current clock master. Ignoring");
- return;
- }
-
- /* Check if we know about this one */
- for (l = domain->pending_syncs.head; l; l = l->next) {
- PtpPendingSync *tmp = l->data;
-
- if (tmp->sync_seqnum == msg->sequence_id) {
- sync = tmp;
- break;
- }
- }
-
- if (!sync) {
- GST_TRACE ("Ignoring FOLLOW_UP with no pending SYNC");
- return;
- }
-
- /* Got a FOLLOW_UP for this already */
- if (sync->sync_send_time_remote != GST_CLOCK_TIME_NONE) {
- GST_TRACE ("Got repeat FOLLOW_UP. Ignoring");
- return;
- }
-
- if (sync->sync_recv_time_local >= receive_time) {
- GST_ERROR ("Got bogus follow up in domain %u: %" GST_TIME_FORMAT " > %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (sync->sync_recv_time_local),
- GST_TIME_ARGS (receive_time));
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
- return;
- }
-
- sync->correction_field_sync += msg->correction_field;
- sync->sync_send_time_remote =
- PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific.
- follow_up.precise_origin_timestamp);
- sync->follow_up_recv_time_local = receive_time;
-
- if (domain->last_ptp_sync_time >= sync->sync_send_time_remote) {
- GST_WARNING ("Backwards PTP times in domain %u: %" GST_TIME_FORMAT " >= %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (domain->last_ptp_sync_time),
- GST_TIME_ARGS (sync->sync_send_time_remote));
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
- sync = NULL;
- return;
- }
- domain->last_ptp_sync_time = sync->sync_send_time_remote;
-
- if (send_delay_req (domain, sync)) {
- /* Sent delay request */
- } else {
- update_ptp_time (domain, sync);
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
- sync = NULL;
- }
-}
-
-static void
-handle_delay_resp_message (PtpMessage * msg, GstClockTime receive_time)
-{
- GList *l;
- PtpDomainData *domain = NULL;
- PtpPendingSync *sync = NULL;
-
- /* Don't consider messages with the alternate master flag set */
- if ((msg->flag_field & 0x0100))
- return;
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *tmp = l->data;
-
- if (msg->domain_number == tmp->domain) {
- domain = tmp;
- break;
- }
- }
-
- if (!domain)
- return;
-
- /* If we have a master clock, ignore this message if it's not coming from there */
- if (domain->have_master_clock
- && compare_clock_identity (&domain->master_clock_identity,
- &msg->source_port_identity) != 0)
- return;
-
- /* Not for us */
- if (msg->message_specific.delay_resp.
- requesting_port_identity.clock_identity != ptp_clock_id.clock_identity
- || msg->message_specific.delay_resp.
- requesting_port_identity.port_number != ptp_clock_id.port_number)
- return;
-
- domain->min_delay_req_interval =
- log2_to_clock_time (msg->log_message_interval);
-
- /* Check if we know about this one */
- for (l = domain->pending_syncs.head; l; l = l->next) {
- PtpPendingSync *tmp = l->data;
-
- if (tmp->delay_req_seqnum == msg->sequence_id) {
- sync = tmp;
- break;
- }
- }
-
- if (!sync)
- return;
-
- /* Got a DELAY_RESP for this already */
- if (sync->delay_req_recv_time_remote != GST_CLOCK_TIME_NONE)
- return;
-
- if (sync->delay_req_send_time_local > receive_time) {
- GST_ERROR ("Got bogus delay response in domain %u: %" GST_TIME_FORMAT " > %"
- GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (sync->delay_req_send_time_local),
- GST_TIME_ARGS (receive_time));
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
- return;
- }
-
- sync->correction_field_delay = msg->correction_field;
-
- sync->delay_req_recv_time_remote =
- PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific.
- delay_resp.receive_timestamp);
- sync->delay_resp_recv_time_local = receive_time;
-
- if (domain->mean_path_delay != 0
- && sync->sync_send_time_remote > sync->delay_req_recv_time_remote) {
- GST_WARNING ("Sync send time after delay req receive time for domain %u: %"
- GST_TIME_FORMAT " > %" GST_TIME_FORMAT, domain->domain,
- GST_TIME_ARGS (sync->sync_send_time_remote),
- GST_TIME_ARGS (sync->delay_req_recv_time_remote));
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
- return;
- }
-
- if (update_mean_path_delay (domain, sync))
- update_ptp_time (domain, sync);
- g_queue_remove (&domain->pending_syncs, sync);
- ptp_pending_sync_free (sync);
-}
-
-static void
-handle_ptp_message (PtpMessage * msg, GstClockTime receive_time)
-{
- /* Ignore our own messages */
- if (msg->source_port_identity.clock_identity == ptp_clock_id.clock_identity &&
- msg->source_port_identity.port_number == ptp_clock_id.port_number) {
- GST_TRACE ("Ignoring our own message");
- return;
- }
-
- GST_TRACE ("Message type %d receive_time %" GST_TIME_FORMAT,
- msg->message_type, GST_TIME_ARGS (receive_time));
- switch (msg->message_type) {
- case PTP_MESSAGE_TYPE_ANNOUNCE:
- handle_announce_message (msg, receive_time);
- break;
- case PTP_MESSAGE_TYPE_SYNC:
- handle_sync_message (msg, receive_time);
- break;
- case PTP_MESSAGE_TYPE_FOLLOW_UP:
- handle_follow_up_message (msg, receive_time);
- break;
- case PTP_MESSAGE_TYPE_DELAY_RESP:
- handle_delay_resp_message (msg, receive_time);
- break;
- default:
- break;
- }
-}
-
-static gboolean
-have_stdin_data_cb (GIOChannel * channel, GIOCondition condition,
- gpointer user_data)
-{
- GIOStatus status;
- StdIOHeader header;
- gchar buffer[8192];
- GError *err = NULL;
- gsize read;
-
- if ((condition & G_IO_STATUS_EOF)) {
- GST_ERROR ("Got EOF on stdin");
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
-
- status =
- g_io_channel_read_chars (channel, (gchar *) & header, sizeof (header),
- &read, &err);
- if (status == G_IO_STATUS_ERROR) {
- GST_ERROR ("Failed to read from stdin: %s", err->message);
- g_clear_error (&err);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status == G_IO_STATUS_EOF) {
- GST_ERROR ("Got EOF on stdin");
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status != G_IO_STATUS_NORMAL) {
- GST_ERROR ("Unexpected stdin read status: %d", status);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (read != sizeof (header)) {
- GST_ERROR ("Unexpected read size: %" G_GSIZE_FORMAT, read);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (header.size > 8192) {
- GST_ERROR ("Unexpected size: %u", header.size);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
-
- status = g_io_channel_read_chars (channel, buffer, header.size, &read, &err);
- if (status == G_IO_STATUS_ERROR) {
- GST_ERROR ("Failed to read from stdin: %s", err->message);
- g_clear_error (&err);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status == G_IO_STATUS_EOF) {
- GST_ERROR ("EOF on stdin");
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (status != G_IO_STATUS_NORMAL) {
- GST_ERROR ("Unexpected stdin read status: %d", status);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- } else if (read != header.size) {
- GST_ERROR ("Unexpected read size: %" G_GSIZE_FORMAT, read);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
-
- switch (header.type) {
- case TYPE_EVENT:
- case TYPE_GENERAL:{
- GstClockTime receive_time = gst_clock_get_time (observation_system_clock);
- PtpMessage msg;
-
- if (parse_ptp_message (&msg, (const guint8 *) buffer, header.size)) {
- dump_ptp_message (&msg);
- handle_ptp_message (&msg, receive_time);
- }
- break;
- }
- default:
- case TYPE_CLOCK_ID:{
- if (header.size != 8) {
- GST_ERROR ("Unexpected clock id size (%u != 8)", header.size);
- g_main_loop_quit (main_loop);
- return G_SOURCE_REMOVE;
- }
- g_mutex_lock (&ptp_lock);
- ptp_clock_id.clock_identity = GST_READ_UINT64_BE (buffer);
- ptp_clock_id.port_number = getpid ();
- GST_DEBUG ("Got clock id 0x%016" G_GINT64_MODIFIER "x %u",
- ptp_clock_id.clock_identity, ptp_clock_id.port_number);
- g_cond_signal (&ptp_cond);
- g_mutex_unlock (&ptp_lock);
- break;
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-/* Cleanup all announce messages and announce message senders
- * that are timed out by now, and clean up all pending syncs
- * that are missing their FOLLOW_UP or DELAY_RESP */
-static gboolean
-cleanup_cb (gpointer data)
-{
- GstClockTime now = gst_clock_get_time (observation_system_clock);
- GList *l, *m, *n;
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *domain = l->data;
-
- for (n = domain->announce_senders; n;) {
- PtpAnnounceSender *sender = n->data;
- gboolean timed_out = TRUE;
-
- /* Keep only 5 messages per sender around */
- while (g_queue_get_length (&sender->announce_messages) > 5) {
- PtpAnnounceMessage *msg = g_queue_pop_head (&sender->announce_messages);
- g_free (msg);
- }
-
- for (m = sender->announce_messages.head; m; m = m->next) {
- PtpAnnounceMessage *msg = m->data;
-
- if (msg->receive_time +
- sender->announce_interval * PTP_ANNOUNCE_RECEIPT_TIMEOUT > now) {
- timed_out = FALSE;
- break;
- }
- }
-
- if (timed_out) {
- GST_DEBUG ("Announce sender 0x%016" G_GINT64_MODIFIER "x %u timed out",
- sender->master_clock_identity.clock_identity,
- sender->master_clock_identity.port_number);
- g_queue_foreach (&sender->announce_messages, (GFunc) g_free, NULL);
- g_queue_clear (&sender->announce_messages);
- }
-
- if (g_queue_get_length (&sender->announce_messages) == 0) {
- GList *tmp = n->next;
-
- if (compare_clock_identity (&sender->master_clock_identity,
- &domain->master_clock_identity) == 0)
- GST_WARNING ("currently selected master clock timed out");
- g_free (sender);
- domain->announce_senders =
- g_list_delete_link (domain->announce_senders, n);
- n = tmp;
- } else {
- n = n->next;
- }
- }
- select_best_master_clock (domain, now);
-
- /* Clean up any pending syncs */
- for (n = domain->pending_syncs.head; n;) {
- PtpPendingSync *sync = n->data;
- gboolean timed_out = FALSE;
-
- /* Time out pending syncs after 4 sync intervals or 10 seconds,
- * and pending delay reqs after 4 delay req intervals or 10 seconds
- */
- if (sync->delay_req_send_time_local != GST_CLOCK_TIME_NONE &&
- ((domain->min_delay_req_interval != 0
- && sync->delay_req_send_time_local +
- 4 * domain->min_delay_req_interval < now)
- || (sync->delay_req_send_time_local + 10 * GST_SECOND < now))) {
- timed_out = TRUE;
- } else if ((domain->sync_interval != 0
- && sync->sync_recv_time_local + 4 * domain->sync_interval < now)
- || (sync->sync_recv_time_local + 10 * GST_SECOND < now)) {
- timed_out = TRUE;
- }
-
- if (timed_out) {
- GList *tmp = n->next;
- ptp_pending_sync_free (sync);
- g_queue_delete_link (&domain->pending_syncs, n);
- n = tmp;
- } else {
- n = n->next;
- }
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static gpointer
-ptp_helper_main (gpointer data)
-{
- GSource *cleanup_source;
-
- GST_DEBUG ("Starting PTP helper loop");
-
- /* Check all 5 seconds, if we have to cleanup ANNOUNCE or pending syncs message */
- cleanup_source = g_timeout_source_new_seconds (5);
- g_source_set_priority (cleanup_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (cleanup_source, (GSourceFunc) cleanup_cb, NULL, NULL);
- g_source_attach (cleanup_source, main_context);
- g_source_unref (cleanup_source);
-
- g_main_loop_run (main_loop);
- GST_DEBUG ("Stopped PTP helper loop");
-
- g_mutex_lock (&ptp_lock);
- ptp_clock_id.clock_identity = GST_PTP_CLOCK_ID_NONE;
- ptp_clock_id.port_number = 0;
- initted = FALSE;
- g_cond_signal (&ptp_cond);
- g_mutex_unlock (&ptp_lock);
-
- return NULL;
-}
-
-/**
- * gst_ptp_is_supported:
- *
- * Check if PTP clocks are generally supported on this system, and if previous
- * initializations did not fail.
- *
- * Returns: %TRUE if PTP clocks are generally supported on this system, and
- * previous initializations did not fail.
- *
- * Since: 1.6
- */
-gboolean
-gst_ptp_is_supported (void)
-{
- return supported;
-}
-
-/**
- * gst_ptp_is_initialized:
- *
- * Check if the GStreamer PTP clock subsystem is initialized.
- *
- * Returns: %TRUE if the GStreamer PTP clock subsystem is initialized.
- *
- * Since: 1.6
- */
-gboolean
-gst_ptp_is_initialized (void)
-{
- return initted;
-}
-
-/**
- * gst_ptp_init:
- * @clock_id: PTP clock id of this process' clock or %GST_PTP_CLOCK_ID_NONE
- * @interfaces: (transfer none) (array zero-terminated=1) (allow-none): network interfaces to run the clock on
- *
- * Initialize the GStreamer PTP subsystem and create a PTP ordinary clock in
- * slave-only mode for all domains on the given @interfaces with the
- * given @clock_id.
- *
- * If @clock_id is %GST_PTP_CLOCK_ID_NONE, a clock id is automatically
- * generated from the MAC address of the first network interface.
- *
- * This function is automatically called by gst_ptp_clock_new() with default
- * parameters if it wasn't called before.
- *
- * Returns: %TRUE if the GStreamer PTP clock subsystem could be initialized.
- *
- * Since: 1.6
- */
-gboolean
-gst_ptp_init (guint64 clock_id, gchar ** interfaces)
-{
- gboolean ret;
- const gchar *env;
- gchar **argv = NULL;
- gint argc, argc_c;
- gint fd_r, fd_w;
- GError *err = NULL;
- GSource *stdin_source;
-
- GST_DEBUG_CATEGORY_INIT (ptp_debug, "ptp", 0, "PTP clock");
-
- g_mutex_lock (&ptp_lock);
- if (!supported) {
- GST_ERROR ("PTP not supported");
- ret = FALSE;
- goto done;
- }
-
- if (initted) {
- GST_DEBUG ("PTP already initialized");
- ret = TRUE;
- goto done;
- }
-
- if (ptp_helper_pid) {
- GST_DEBUG ("PTP currently initializing");
- goto wait;
- }
-
- if (!domain_stats_hooks_initted) {
- g_hook_list_init (&domain_stats_hooks, sizeof (GHook));
- domain_stats_hooks_initted = TRUE;
- }
-
- argc = 1;
- if (clock_id != GST_PTP_CLOCK_ID_NONE)
- argc += 2;
- if (interfaces != NULL)
- argc += 2 * g_strv_length (interfaces);
-
- argv = g_new0 (gchar *, argc + 2);
- argc_c = 0;
-
- env = g_getenv ("GST_PTP_HELPER_1_0");
- if (env == NULL)
- env = g_getenv ("GST_PTP_HELPER");
- if (env != NULL && *env != '\0') {
- GST_LOG ("Trying GST_PTP_HELPER env var: %s", env);
- argv[argc_c++] = g_strdup (env);
- } else {
- argv[argc_c++] = g_strdup (GST_PTP_HELPER_INSTALLED);
- }
-
- if (clock_id != GST_PTP_CLOCK_ID_NONE) {
- argv[argc_c++] = g_strdup ("-c");
- argv[argc_c++] = g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", clock_id);
- }
-
- if (interfaces != NULL) {
- gchar **ptr = interfaces;
-
- while (*ptr) {
- argv[argc_c++] = g_strdup ("-i");
- argv[argc_c++] = g_strdup (*ptr);
- ptr++;
- }
- }
-
- main_context = g_main_context_new ();
- main_loop = g_main_loop_new (main_context, FALSE);
-
- ptp_helper_thread =
- g_thread_try_new ("ptp-helper-thread", ptp_helper_main, NULL, &err);
- if (!ptp_helper_thread) {
- GST_ERROR ("Failed to start PTP helper thread: %s", err->message);
- g_clear_error (&err);
- ret = FALSE;
- goto done;
- }
-
- if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL,
- &ptp_helper_pid, &fd_w, &fd_r, NULL, &err)) {
- GST_ERROR ("Failed to start ptp helper process: %s", err->message);
- g_clear_error (&err);
- ret = FALSE;
- supported = FALSE;
- goto done;
- }
-
- stdin_channel = g_io_channel_unix_new (fd_r);
- g_io_channel_set_encoding (stdin_channel, NULL, NULL);
- g_io_channel_set_buffered (stdin_channel, FALSE);
- g_io_channel_set_close_on_unref (stdin_channel, TRUE);
- stdin_source =
- g_io_create_watch (stdin_channel, G_IO_IN | G_IO_PRI | G_IO_HUP);
- g_source_set_priority (stdin_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (stdin_source, (GSourceFunc) have_stdin_data_cb, NULL,
- NULL);
- g_source_attach (stdin_source, main_context);
- g_source_unref (stdin_source);
-
- /* Create stdout channel */
- stdout_channel = g_io_channel_unix_new (fd_w);
- g_io_channel_set_encoding (stdout_channel, NULL, NULL);
- g_io_channel_set_close_on_unref (stdout_channel, TRUE);
- g_io_channel_set_buffered (stdout_channel, FALSE);
-
- delay_req_rand = g_rand_new ();
- observation_system_clock =
- g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "ptp-observation-clock",
- NULL);
- gst_object_ref_sink (observation_system_clock);
-
- initted = TRUE;
-
-wait:
- GST_DEBUG ("Waiting for PTP to be initialized");
-
- while (ptp_clock_id.clock_identity == GST_PTP_CLOCK_ID_NONE && initted)
- g_cond_wait (&ptp_cond, &ptp_lock);
-
- ret = initted;
- if (ret) {
- GST_DEBUG ("Initialized and got clock id 0x%016" G_GINT64_MODIFIER "x %u",
- ptp_clock_id.clock_identity, ptp_clock_id.port_number);
- } else {
- GST_ERROR ("Failed to initialize");
- supported = FALSE;
- }
-
-done:
- g_strfreev (argv);
-
- if (!ret) {
- if (ptp_helper_pid) {
-#ifndef G_OS_WIN32
- kill (ptp_helper_pid, SIGKILL);
- waitpid (ptp_helper_pid, NULL, 0);
-#else
- TerminateProcess (ptp_helper_pid, 1);
- WaitForSingleObject (ptp_helper_pid, INFINITE);
-#endif
- g_spawn_close_pid (ptp_helper_pid);
- }
- ptp_helper_pid = 0;
-
- if (stdin_channel)
- g_io_channel_unref (stdin_channel);
- stdin_channel = NULL;
- if (stdout_channel)
- g_io_channel_unref (stdout_channel);
- stdout_channel = NULL;
-
- if (main_loop && ptp_helper_thread) {
- g_main_loop_quit (main_loop);
- g_thread_join (ptp_helper_thread);
- }
- ptp_helper_thread = NULL;
- if (main_loop)
- g_main_loop_unref (main_loop);
- main_loop = NULL;
- if (main_context)
- g_main_context_unref (main_context);
- main_context = NULL;
-
- if (delay_req_rand)
- g_rand_free (delay_req_rand);
- delay_req_rand = NULL;
-
- if (observation_system_clock)
- gst_object_unref (observation_system_clock);
- observation_system_clock = NULL;
- }
-
- g_mutex_unlock (&ptp_lock);
-
- return ret;
-}
-
-/**
- * gst_ptp_deinit:
- *
- * Deinitialize the GStreamer PTP subsystem and stop the PTP clock. If there
- * are any remaining GstPtpClock instances, they won't be further synchronized
- * to the PTP network clock.
- *
- * Since: 1.6
- */
-void
-gst_ptp_deinit (void)
-{
- GList *l, *m;
-
- g_mutex_lock (&ptp_lock);
-
- if (ptp_helper_pid) {
-#ifndef G_OS_WIN32
- kill (ptp_helper_pid, SIGKILL);
- waitpid (ptp_helper_pid, NULL, 0);
-#else
- TerminateProcess (ptp_helper_pid, 1);
- WaitForSingleObject (ptp_helper_pid, INFINITE);
-#endif
- g_spawn_close_pid (ptp_helper_pid);
- }
- ptp_helper_pid = 0;
-
- if (stdin_channel)
- g_io_channel_unref (stdin_channel);
- stdin_channel = NULL;
- if (stdout_channel)
- g_io_channel_unref (stdout_channel);
- stdout_channel = NULL;
-
- if (main_loop && ptp_helper_thread) {
- GThread *tmp = ptp_helper_thread;
- ptp_helper_thread = NULL;
- g_mutex_unlock (&ptp_lock);
- g_main_loop_quit (main_loop);
- g_thread_join (tmp);
- g_mutex_lock (&ptp_lock);
- }
- if (main_loop)
- g_main_loop_unref (main_loop);
- main_loop = NULL;
- if (main_context)
- g_main_context_unref (main_context);
- main_context = NULL;
-
- if (delay_req_rand)
- g_rand_free (delay_req_rand);
- delay_req_rand = NULL;
- if (observation_system_clock)
- gst_object_unref (observation_system_clock);
- observation_system_clock = NULL;
-
- for (l = domain_data; l; l = l->next) {
- PtpDomainData *domain = l->data;
-
- for (m = domain->announce_senders; m; m = m->next) {
- PtpAnnounceSender *sender = m->data;
-
- g_queue_foreach (&sender->announce_messages, (GFunc) g_free, NULL);
- g_queue_clear (&sender->announce_messages);
- g_free (sender);
- }
- g_list_free (domain->announce_senders);
-
- g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free,
- NULL);
- g_queue_clear (&domain->pending_syncs);
- gst_object_unref (domain->domain_clock);
- g_free (domain);
- }
- g_list_free (domain_data);
- domain_data = NULL;
- g_list_foreach (domain_clocks, (GFunc) g_free, NULL);
- g_list_free (domain_clocks);
- domain_clocks = NULL;
-
- ptp_clock_id.clock_identity = GST_PTP_CLOCK_ID_NONE;
- ptp_clock_id.port_number = 0;
-
- initted = FALSE;
-
- g_mutex_unlock (&ptp_lock);
-}
-
-#define DEFAULT_DOMAIN 0
-
-enum
-{
- PROP_0,
- PROP_DOMAIN,
- PROP_INTERNAL_CLOCK,
- PROP_MASTER_CLOCK_ID,
- PROP_GRANDMASTER_CLOCK_ID
-};
-
-struct _GstPtpClockPrivate
-{
- guint domain;
- GstClock *domain_clock;
- gulong domain_stats_id;
-};
-
-#define gst_ptp_clock_parent_class parent_class
-G_DEFINE_TYPE_WITH_PRIVATE (GstPtpClock, gst_ptp_clock, GST_TYPE_SYSTEM_CLOCK);
-
-static void gst_ptp_clock_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_ptp_clock_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void gst_ptp_clock_finalize (GObject * object);
-
-static GstClockTime gst_ptp_clock_get_internal_time (GstClock * clock);
-
-static void
-gst_ptp_clock_class_init (GstPtpClockClass * klass)
-{
- GObjectClass *gobject_class;
- GstClockClass *clock_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- clock_class = GST_CLOCK_CLASS (klass);
-
- gobject_class->finalize = gst_ptp_clock_finalize;
- gobject_class->get_property = gst_ptp_clock_get_property;
- gobject_class->set_property = gst_ptp_clock_set_property;
-
- g_object_class_install_property (gobject_class, PROP_DOMAIN,
- g_param_spec_uint ("domain", "Domain",
- "The PTP domain", 0, G_MAXUINT8,
- DEFAULT_DOMAIN,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_INTERNAL_CLOCK,
- g_param_spec_object ("internal-clock", "Internal Clock",
- "Internal clock", GST_TYPE_CLOCK,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_MASTER_CLOCK_ID,
- g_param_spec_uint64 ("master-clock-id", "Master Clock ID",
- "Master Clock ID", 0, G_MAXUINT64, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (gobject_class, PROP_GRANDMASTER_CLOCK_ID,
- g_param_spec_uint64 ("grandmaster-clock-id", "Grand Master Clock ID",
- "Grand Master Clock ID", 0, G_MAXUINT64, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- clock_class->get_internal_time = gst_ptp_clock_get_internal_time;
-}
-
-static void
-gst_ptp_clock_init (GstPtpClock * self)
-{
- GstPtpClockPrivate *priv;
-
- self->priv = priv = gst_ptp_clock_get_instance_private (self);
-
- GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_CAN_SET_MASTER);
- GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC);
-
- priv->domain = DEFAULT_DOMAIN;
-}
-
-static gboolean
-gst_ptp_clock_ensure_domain_clock (GstPtpClock * self)
-{
- gboolean got_clock = TRUE;
-
- if (G_UNLIKELY (!self->priv->domain_clock)) {
- g_mutex_lock (&domain_clocks_lock);
- if (!self->priv->domain_clock) {
- GList *l;
-
- got_clock = FALSE;
-
- for (l = domain_clocks; l; l = l->next) {
- PtpDomainData *clock_data = l->data;
-
- if (clock_data->domain == self->priv->domain &&
- clock_data->have_master_clock && clock_data->last_ptp_time != 0) {
- GST_DEBUG ("Switching domain clock on domain %d", clock_data->domain);
- self->priv->domain_clock = clock_data->domain_clock;
- got_clock = TRUE;
- break;
- }
- }
- }
- g_mutex_unlock (&domain_clocks_lock);
- if (got_clock) {
- g_object_notify (G_OBJECT (self), "internal-clock");
- gst_clock_set_synced (GST_CLOCK (self), TRUE);
- }
- }
-
- return got_clock;
-}
-
-static gboolean
-gst_ptp_clock_stats_callback (guint8 domain, const GstStructure * stats,
- gpointer user_data)
-{
- GstPtpClock *self = user_data;
-
- if (domain != self->priv->domain
- || !gst_structure_has_name (stats, GST_PTP_STATISTICS_TIME_UPDATED))
- return TRUE;
-
- /* Let's set our internal clock */
- if (!gst_ptp_clock_ensure_domain_clock (self))
- return TRUE;
-
- self->priv->domain_stats_id = 0;
-
- return FALSE;
-}
-
-static void
-gst_ptp_clock_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstPtpClock *self = GST_PTP_CLOCK (object);
-
- switch (prop_id) {
- case PROP_DOMAIN:
- self->priv->domain = g_value_get_uint (value);
- gst_ptp_clock_ensure_domain_clock (self);
- if (!self->priv->domain_clock)
- self->priv->domain_stats_id =
- gst_ptp_statistics_callback_add (gst_ptp_clock_stats_callback, self,
- NULL);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_ptp_clock_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstPtpClock *self = GST_PTP_CLOCK (object);
-
- switch (prop_id) {
- case PROP_DOMAIN:
- g_value_set_uint (value, self->priv->domain);
- break;
- case PROP_INTERNAL_CLOCK:
- gst_ptp_clock_ensure_domain_clock (self);
- g_value_set_object (value, self->priv->domain_clock);
- break;
- case PROP_MASTER_CLOCK_ID:
- case PROP_GRANDMASTER_CLOCK_ID:{
- GList *l;
-
- g_mutex_lock (&domain_clocks_lock);
- g_value_set_uint64 (value, 0);
-
- for (l = domain_clocks; l; l = l->next) {
- PtpDomainData *clock_data = l->data;
-
- if (clock_data->domain == self->priv->domain) {
- if (prop_id == PROP_MASTER_CLOCK_ID)
- g_value_set_uint64 (value,
- clock_data->master_clock_identity.clock_identity);
- else
- g_value_set_uint64 (value, clock_data->grandmaster_identity);
- break;
- }
- }
- g_mutex_unlock (&domain_clocks_lock);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_ptp_clock_finalize (GObject * object)
-{
- GstPtpClock *self = GST_PTP_CLOCK (object);
-
- if (self->priv->domain_stats_id)
- gst_ptp_statistics_callback_remove (self->priv->domain_stats_id);
-
- G_OBJECT_CLASS (gst_ptp_clock_parent_class)->finalize (object);
-}
-
-static GstClockTime
-gst_ptp_clock_get_internal_time (GstClock * clock)
-{
- GstPtpClock *self = GST_PTP_CLOCK (clock);
-
- gst_ptp_clock_ensure_domain_clock (self);
-
- if (!self->priv->domain_clock) {
- GST_ERROR_OBJECT (self, "Domain %u has no clock yet and is not synced",
- self->priv->domain);
- return GST_CLOCK_TIME_NONE;
- }
-
- return gst_clock_get_time (self->priv->domain_clock);
-}
-
-/**
- * gst_ptp_clock_new:
- * @name: Name of the clock
- * @domain: PTP domain
- *
- * Creates a new PTP clock instance that exports the PTP time of the master
- * clock in @domain. This clock can be slaved to other clocks as needed.
- *
- * If gst_ptp_init() was not called before, this will call gst_ptp_init() with
- * default parameters.
- *
- * This clock only returns valid timestamps after it received the first
- * times from the PTP master clock on the network. Once this happens the
- * GstPtpClock::internal-clock property will become non-NULL. You can
- * check this with gst_clock_wait_for_sync(), the GstClock::synced signal and
- * gst_clock_is_synced().
- *
- * Returns: (transfer full): A new #GstClock
- *
- * Since: 1.6
- */
-GstClock *
-gst_ptp_clock_new (const gchar * name, guint domain)
-{
- GstClock *clock;
-
- g_return_val_if_fail (domain <= G_MAXUINT8, NULL);
-
- if (!initted && !gst_ptp_init (GST_PTP_CLOCK_ID_NONE, NULL)) {
- GST_ERROR ("Failed to initialize PTP");
- return NULL;
- }
-
- clock = g_object_new (GST_TYPE_PTP_CLOCK, "name", name, "domain", domain,
- NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (clock);
-
- return clock;
-}
-
-typedef struct
-{
- guint8 domain;
- const GstStructure *stats;
-} DomainStatsMarshalData;
-
-static void
-domain_stats_marshaller (GHook * hook, DomainStatsMarshalData * data)
-{
- GstPtpStatisticsCallback callback = (GstPtpStatisticsCallback) hook->func;
-
- if (!callback (data->domain, data->stats, hook->data))
- g_hook_destroy (&domain_stats_hooks, hook->hook_id);
-}
-
-static void
-emit_ptp_statistics (guint8 domain, const GstStructure * stats)
-{
- DomainStatsMarshalData data = { domain, stats };
-
- g_mutex_lock (&ptp_lock);
- g_hook_list_marshal (&domain_stats_hooks, TRUE,
- (GHookMarshaller) domain_stats_marshaller, &data);
- g_mutex_unlock (&ptp_lock);
-}
-
-/**
- * gst_ptp_statistics_callback_add:
- * @callback: GstPtpStatisticsCallback to call
- * @user_data: Data to pass to the callback
- * @destroy_data: GDestroyNotify to destroy the data
- *
- * Installs a new statistics callback for gathering PTP statistics. See
- * GstPtpStatisticsCallback for a list of statistics that are provided.
- *
- * Returns: Id for the callback that can be passed to
- * gst_ptp_statistics_callback_remove()
- *
- * Since: 1.6
- */
-gulong
-gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback,
- gpointer user_data, GDestroyNotify destroy_data)
-{
- GHook *hook;
-
- g_mutex_lock (&ptp_lock);
-
- if (!domain_stats_hooks_initted) {
- g_hook_list_init (&domain_stats_hooks, sizeof (GHook));
- domain_stats_hooks_initted = TRUE;
- }
-
- hook = g_hook_alloc (&domain_stats_hooks);
- hook->func = callback;
- hook->data = user_data;
- hook->destroy = destroy_data;
- g_hook_prepend (&domain_stats_hooks, hook);
- g_atomic_int_add (&domain_stats_n_hooks, 1);
-
- g_mutex_unlock (&ptp_lock);
-
- return hook->hook_id;
-}
-
-/**
- * gst_ptp_statistics_callback_remove:
- * @id: Callback id to remove
- *
- * Removes a PTP statistics callback that was previously added with
- * gst_ptp_statistics_callback_add().
- *
- * Since: 1.6
- */
-void
-gst_ptp_statistics_callback_remove (gulong id)
-{
- g_mutex_lock (&ptp_lock);
- if (g_hook_destroy (&domain_stats_hooks, id))
- g_atomic_int_add (&domain_stats_n_hooks, -1);
- g_mutex_unlock (&ptp_lock);
-}
diff --git a/libs/gst/net/gstptpclock.h b/libs/gst/net/gstptpclock.h
deleted file mode 100644
index 3182431b9f..0000000000
--- a/libs/gst/net/gstptpclock.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* GStreamer
- * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_PTP_CLOCK_H__
-#define __GST_PTP_CLOCK_H__
-
-#include <gst/gst.h>
-#include <gst/gstsystemclock.h>
-#include <gst/net/net-prelude.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_PTP_CLOCK \
- (gst_ptp_clock_get_type())
-#define GST_PTP_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PTP_CLOCK,GstPtpClock))
-#define GST_PTP_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PTP_CLOCK,GstPtpClockClass))
-#define GST_IS_PTP_CLOCK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PTP_CLOCK))
-#define GST_IS_PTP_CLOCK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PTP_CLOCK))
-
-typedef struct _GstPtpClock GstPtpClock;
-typedef struct _GstPtpClockClass GstPtpClockClass;
-typedef struct _GstPtpClockPrivate GstPtpClockPrivate;
-
-/**
- * GstPtpClock:
- *
- * Opaque #GstPtpClock structure.
- */
-struct _GstPtpClock {
- GstSystemClock clock;
-
- /*< private >*/
- GstPtpClockPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstPtpClockClass:
- * @parent_class: parented to #GstSystemClockClass
- *
- * Opaque #GstPtpClockClass structure.
- */
-struct _GstPtpClockClass {
- GstSystemClockClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GST_PTP_CLOCK_ID_NONE:
- * PTP clock identification that can be passed to gst_ptp_init() to
- * automatically select one based on the MAC address of interfaces
- */
-#define GST_PTP_CLOCK_ID_NONE ((guint64) -1)
-
-GST_NET_API
-GType gst_ptp_clock_get_type (void);
-
-GST_NET_API
-gboolean gst_ptp_is_supported (void);
-
-GST_NET_API
-gboolean gst_ptp_is_initialized (void);
-
-GST_NET_API
-gboolean gst_ptp_init (guint64 clock_id,
- gchar ** interfaces);
-GST_NET_API
-void gst_ptp_deinit (void);
-
-#define GST_PTP_STATISTICS_NEW_DOMAIN_FOUND "GstPtpStatisticsNewDomainFound"
-#define GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED "GstPtpStatisticsBestMasterClockSelected"
-#define GST_PTP_STATISTICS_PATH_DELAY_MEASURED "GstPtpStatisticsPathDelayMeasured"
-#define GST_PTP_STATISTICS_TIME_UPDATED "GstPtpStatisticsTimeUpdated"
-
-/**
- * GstPtpStatisticsCallback:
- * @domain: PTP domain identifier
- * @stats: New statistics
- * @user_data: Data passed to gst_ptp_statistics_callback_add()
- *
- * The statistics can be the following structures:
- *
- * GST_PTP_STATISTICS_NEW_DOMAIN_FOUND:
- * "domain" G_TYPE_UINT The domain identifier of the domain
- * "clock" GST_TYPE_CLOCK The internal clock that is slaved to the
- * PTP domain
- *
- * GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED:
- * "domain" G_TYPE_UINT The domain identifier of the domain
- * "master-clock-id" G_TYPE_UINT64 PTP clock identifier of the selected master
- * clock
- * "master-clock-port" G_TYPE_UINT PTP port number of the selected master clock
- * "grandmaster-clock-id" G_TYPE_UINT64 PTP clock identifier of the grandmaster clock
- *
- * GST_PTP_STATISTICS_PATH_DELAY_MEASURED:
- * "domain" G_TYPE_UINT The domain identifier of the domain
- * "mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay
- * "mean-path-delay" GST_TYPE_CLOCK_TIME Latest mean path delay
- * "delay-request-delay" GST_TYPE_CLOCK_TIME Delay of DELAY_REQ / DELAY_RESP messages
- *
- * GST_PTP_STATISTICS_TIME_UPDATED:
- * "domain" G_TYPE_UINT The domain identifier of the domain
- * "mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay
- * "local-time" GST_TYPE_CLOCK_TIME Local time that corresponds to ptp-time
- * "ptp-time" GST_TYPE_CLOCK_TIME Newly measured PTP time at local-time
- * "estimated-ptp-time" GST_TYPE_CLOCK_TIME Estimated PTP time based on previous measurements
- * "discontinuity" G_TYPE_INT64 Difference between estimated and measured PTP time
- * "synced" G_TYPE_BOOLEAN Currently synced to the remote clock
- * "r-squared" G_TYPE_DOUBLE R² of clock estimation regression
- * "internal-time" GST_TYPE_CLOCK_TIME Internal time clock parameter
- * "external-time" GST_TYPE_CLOCK_TIME External time clock parameter
- * "rate-num" G_TYPE_UINT64 Internal/external rate numerator
- * "rate-den" G_TYPE_UINT64 Internal/external rate denominator
- * "rate" G_TYPE_DOUBLE Internal/external rate
- *
- * If %FALSE is returned, the callback is removed and never called again.
- *
- */
-typedef gboolean (*GstPtpStatisticsCallback) (guint8 domain,
- const GstStructure * stats,
- gpointer user_data);
-GST_NET_API
-gulong gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback,
- gpointer user_data, GDestroyNotify destroy_data);
-GST_NET_API
-void gst_ptp_statistics_callback_remove (gulong id);
-
-GST_NET_API
-GstClock* gst_ptp_clock_new (const gchar *name,
- guint domain);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPtpClock, gst_object_unref)
-
-G_END_DECLS
-
-#endif /* __GST_PTP_CLOCK_H__ */
-
diff --git a/libs/gst/net/meson.build b/libs/gst/net/meson.build
deleted file mode 100644
index f63ae281b7..0000000000
--- a/libs/gst/net/meson.build
+++ /dev/null
@@ -1,69 +0,0 @@
-gst_net_sources = [
- 'gstnetaddressmeta.c',
- 'gstnetclientclock.c',
- 'gstnetcontrolmessagemeta.c',
- 'gstnettimepacket.c',
- 'gstnettimeprovider.c',
- 'gstptpclock.c',
- 'gstntppacket.c',
- 'gstnetutils.c',
-]
-
-gst_net_headers = [
- 'gstnet.h',
- 'gstnetaddressmeta.h',
- 'gstnetclientclock.h',
- 'gstnetcontrolmessagemeta.h',
- 'gstnettimepacket.h',
- 'gstnettimeprovider.h',
- 'gstnetutils.h',
- 'gstptpclock.h',
- 'net-prelude.h',
- 'net.h',
-]
-install_headers(gst_net_headers, subdir : 'gstreamer-1.0/gst/net/')
-
-gst_net_gen_sources = []
-gst_net = library('gstnet-@0@'.format(apiversion),
- gst_net_sources,
- c_args : gst_c_args + ['-DBUILDING_GST_NET'],
- include_directories : [configinc, libsinc],
- version : libversion,
- soversion : soversion,
- darwin_versions : osxversion,
- install : true,
- dependencies : [gio_dep, gst_base_dep],
-)
-
-pkgconfig.generate(gst_net,
- libraries : [libgst],
- variables : pkgconfig_variables,
- subdirs : pkgconfig_subdirs,
- name : 'gstreamer-net-1.0',
- description : 'Network-enabled GStreamer plug-ins and clocking',
-)
-
-if build_gir
- gst_gir_extra_args = gir_init_section + [ '--c-include=gst/net/net.h' ]
- gst_net_gir = gnome.generate_gir(gst_net,
- sources : gst_net_sources + gst_net_headers,
- namespace : 'GstNet',
- nsversion : apiversion,
- identifier_prefix : 'Gst',
- symbol_prefix : 'gst',
- export_packages : 'gstreamer-net-1.0',
- dependencies : [gst_base_dep],
- include_directories : [configinc, libsinc],
- includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gio-2.0', 'Gst-1.0'],
- install : true,
- extra_args : gst_gir_extra_args,
- )
- gst_net_gen_sources += [gst_net_gir]
-endif
-
-gst_net_dep = declare_dependency(link_with : gst_net,
- include_directories : [libsinc],
- sources: gst_net_gen_sources,
- dependencies : [gst_base_dep])
-
-meson.override_dependency('gstreamer-net-1.0', gst_net_dep)
diff --git a/libs/gst/net/net-prelude.h b/libs/gst/net/net-prelude.h
deleted file mode 100644
index 47224fe048..0000000000
--- a/libs/gst/net/net-prelude.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* GStreamer Net Library
- * Copyright (C) 2018 GStreamer developers
- *
- * net-prelude.h: prelude include header for gst-net library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_NET_PRELUDE_H__
-#define __GST_NET_PRELUDE_H__
-
-#include <gst/gst.h>
-
-#ifndef GST_NET_API
-#ifdef BUILDING_GST_NET
-#define GST_NET_API GST_API_EXPORT /* from config.h */
-#else
-#define GST_NET_API GST_API_IMPORT
-#endif
-#endif
-
-#endif /* __GST_NET_PRELUDE_H__ */
diff --git a/libs/gst/net/net.h b/libs/gst/net/net.h
deleted file mode 100644
index 4a11a94f23..0000000000
--- a/libs/gst/net/net.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* GStreamer
- * Copyright (C) 2012 GStreamer developers
- *
- * net.h: single include header for gst-net library
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_NET__H__
-#define __GST_NET__H__
-
-#include <gst/net/net-prelude.h>
-
-#include <gst/net/gstnet.h>
-#include <gst/net/gstnetaddressmeta.h>
-#include <gst/net/gstnetcontrolmessagemeta.h>
-#include <gst/net/gstnetclientclock.h>
-#include <gst/net/gstnettimepacket.h>
-#include <gst/net/gstnettimeprovider.h>
-#include <gst/net/gstnetutils.h>
-#include <gst/net/gstptpclock.h>
-
-#endif /* __GST_NET__H__ */
diff --git a/libs/meson.build b/libs/meson.build
deleted file mode 100644
index 668dcbaaff..0000000000
--- a/libs/meson.build
+++ /dev/null
@@ -1 +0,0 @@
-subdir('gst')