Merge branch 'master' into 0.11-fdo

Conflicts:
	gst/gst.c
	libs/gst/base/gstcollectpads.c
This commit is contained in:
Wim Taymans 2011-03-28 20:11:20 +02:00
commit a12ede3fb1
34 changed files with 531 additions and 112 deletions

View file

@ -84,7 +84,7 @@ tool_run "$libtoolize" "--copy --force"
tool_run "$aclocal" "-I m4 -I common/m4 $ACLOCAL_FLAGS"
tool_run "$autoheader"
# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode -- wingo
# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode
echo timestamp > stamp-h.in 2> /dev/null
tool_run "$autoconf"

2
common

@ -1 +1 @@
Subproject commit 6aec6b9716c184c60c4bc6a5916a2471cfa8c8cd
Subproject commit 1ccbe098d6379612fcef09f4000da23585af980a

View file

@ -54,7 +54,8 @@ SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED"
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Extra options to supply to gtkdoc-fixref.
FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/gst/html \
--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
--extra-dir=$(datadir)/gtk-doc/html
# Used for dependencies.

View file

@ -52,7 +52,9 @@ SCAN_OPTIONS=
MKDB_OPTIONS=--sgml-mode
# Extra options to supply to gtkdoc-fixref.
FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/gst/html \
--extra-dir=$(top_builddir)/docs/libs/html \
--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
--extra-dir=$(datadir)/gtk-doc/html
# Used for dependencies.

View file

@ -149,6 +149,7 @@ GST_INPUT_SELECTOR_WAIT
<FILE>element-queue</FILE>
<TITLE>queue</TITLE>
GstQueue
GstQueueLeaky
<SUBSECTION Standard>
GstQueueClass
GST_QUEUE

View file

@ -754,6 +754,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
g_type_class_ref (gst_buffer_pool_flags_get_type ());
g_type_class_ref (gst_memory_flags_get_type ());
g_type_class_ref (gst_map_flags_get_type ());
g_type_class_ref (gst_caps_intersect_mode_get_type ());
gst_structure_get_type ();
_gst_event_initialize ();
@ -1121,6 +1122,7 @@ gst_deinit (void)
g_type_class_unref (g_type_class_peek (gst_buffer_pool_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_memory_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_map_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ()));
gst_deinitialized = TRUE;
GST_INFO ("deinitialized GStreamer");

View file

@ -2349,11 +2349,8 @@ gst_bin_do_latency_func (GstBin * bin)
GST_TIME_ARGS (min_latency));
} else {
GST_WARNING_OBJECT (element,
"failed to configure latency of %" GST_TIME_FORMAT,
"did not really configure latency of %" GST_TIME_FORMAT,
GST_TIME_ARGS (min_latency));
GST_ELEMENT_WARNING (element, CORE, CLOCK, (NULL),
("Failed to configure latency of %" GST_TIME_FORMAT,
GST_TIME_ARGS (min_latency)));
}
} else {
/* this is not a real problem, we just don't configure any latency. */

View file

@ -1301,18 +1301,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
return FALSE;
}
/**
* gst_caps_intersect:
* @caps1: a #GstCaps to intersect
* @caps2: a #GstCaps to intersect
*
* Creates a new #GstCaps that contains all the formats that are common
* to both @caps1 and @caps2.
*
* Returns: the new #GstCaps
*/
GstCaps *
gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
static GstCaps *
gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
{
guint64 i; /* index can be up to 2 * G_MAX_UINT */
guint j, k, len1, len2;
@ -1322,9 +1312,6 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
GstCaps *dest;
GstStructure *istruct;
g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
/* caps are exactly the same pointers, just copy one caps */
if (G_UNLIKELY (caps1 == caps2))
return _gst_caps_copy (caps1);
@ -1385,6 +1372,109 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
return dest;
}
/**
* gst_caps_intersect_first:
* @caps1: a #GstCaps to intersect
* @caps2: a #GstCaps to intersect
*
* Creates a new #GstCaps that contains all the formats that are common
* to both @caps1 and @caps2.
*
* Unlike @gst_caps_intersect, the returned caps will be ordered in a similar
* fashion as @caps1.
*
* Returns: the new #GstCaps
*/
static GstCaps *
gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2)
{
guint64 i; /* index can be up to 2 * G_MAX_UINT */
guint j, len1, len2;
GstStructure *struct1;
GstStructure *struct2;
GstCaps *dest;
GstStructure *istruct;
/* caps are exactly the same pointers, just copy one caps */
if (G_UNLIKELY (caps1 == caps2))
return gst_caps_copy (caps1);
/* empty caps on either side, return empty */
if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
return gst_caps_new_empty ();
/* one of the caps is any, just copy the other caps */
if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
return gst_caps_copy (caps2);
if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
return gst_caps_copy (caps1);
dest = gst_caps_new_empty ();
len1 = caps1->structs->len;
len2 = caps2->structs->len;
for (i = 0; i < len1; i++) {
struct1 = gst_caps_get_structure_unchecked (caps1, i);
for (j = 0; j < len2; j++) {
struct2 = gst_caps_get_structure_unchecked (caps2, j);
istruct = gst_caps_structure_intersect (struct1, struct2);
if (istruct)
gst_caps_append_structure (dest, istruct);
}
}
return dest;
}
/**
* gst_caps_intersect_full:
* @caps1: a #GstCaps to intersect
* @caps2: a #GstCaps to intersect
* @mode: The intersection algorithm/mode to use
*
* Creates a new #GstCaps that contains all the formats that are common
* to both @caps1 and @caps2, the order is defined by the #GstCapsIntersectMode
* used.
*
* Returns: the new #GstCaps
* Since: 0.10.33
*/
GstCaps *
gst_caps_intersect_full (const GstCaps * caps1, const GstCaps * caps2,
GstCapsIntersectMode mode)
{
g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
switch (mode) {
case GST_CAPS_INTERSECT_FIRST:
return gst_caps_intersect_first (caps1, caps2);
default:
g_warning ("Unknown caps intersect mode: %d", mode);
/* fallthrough */
case GST_CAPS_INTERSECT_ZIG_ZAG:
return gst_caps_intersect_zig_zag (caps1, caps2);
}
}
/**
* gst_caps_intersect:
* @caps1: a #GstCaps to intersect
* @caps2: a #GstCaps to intersect
*
* Creates a new #GstCaps that contains all the formats that are common
* to both @caps1 and @caps2. Defaults to %GST_CAPS_INTERSECT_ZIG_ZAG mode.
*
* Returns: the new #GstCaps
*/
GstCaps *
gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
{
return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG);
}
/* subtract operation */
typedef struct

View file

@ -46,6 +46,37 @@ typedef enum {
GST_CAPS_FLAGS_ANY = (GST_MINI_OBJECT_FLAG_LAST << 0)
} GstCapsFlags;
/**
* GstCapsIntersectMode:
* @GST_CAPS_INTERSECT_ZIG_ZAG : Zig-zags over both caps.
* @GST_CAPS_INTERSECT_FIRST : Keeps the first caps order.
*
* Modes of caps intersection
*
* #GST_CAPS_INTERSECT_ZIG_ZAG tries to preserve overall order of both caps
* by iterating on the caps' structures as the following matrix shows:
* caps1
* +-------------
* | 1 2 4 7
* caps2 | 3 5 8 10
* | 6 9 11 12
*
* Used when there is no explicit precedence of one caps over the other. e.g.
* tee's sink pad getcaps function, it will probe its src pad peers' for their
* caps and intersect them with this mode.
*
* #GST_CAPS_INTERSECT_FIRST is useful when an element wants to preserve
* another element's caps priority order when intersecting with its own caps.
* Example: If caps1 is [A, B, C] and caps2 is [E, B, D, A], the result
* would be [A, B], maintaining the first caps priority on the intersection.
*
* Since: 0.10.33
*/
typedef enum {
GST_CAPS_INTERSECT_ZIG_ZAG = 0,
GST_CAPS_INTERSECT_FIRST = 1
} GstCapsIntersectMode;
/**
* GST_CAPS_ANY:
*
@ -316,6 +347,9 @@ gboolean gst_caps_can_intersect (const GstCaps * caps1,
/* operations */
GstCaps * gst_caps_intersect (const GstCaps *caps1,
const GstCaps *caps2);
GstCaps * gst_caps_intersect_full (const GstCaps *caps1,
const GstCaps *caps2,
GstCapsIntersectMode mode);
GstCaps * gst_caps_subtract (const GstCaps *minuend,
const GstCaps *subtrahend);
GstCaps * gst_caps_union (const GstCaps *caps1,

View file

@ -459,7 +459,7 @@ G_STMT_START { \
*
* Utility function that elements can use in case they want to inform
* the application of something noteworthy that is not an error.
* The pipeline will post a warning message and the
* The pipeline will post a info message and the
* application will be informed.
*
* Since: 0.10.12

View file

@ -93,6 +93,7 @@ typedef enum {
* @GST_EVENT_SINK_MESSAGE: An event that sinks turn into a message. Used to
* send messages that should be emitted in sync with
* rendering.
* Since: 0.10.26
* @GST_EVENT_QOS: A quality message. Used to indicate to upstream elements
* that the downstream elements should adjust their processing
* rate.

View file

@ -200,7 +200,6 @@ release_wakeup (GstPoll * set)
static inline gint
release_all_wakeup (GstPoll * set)
{
gboolean result;
gint old;
while (TRUE) {
@ -211,7 +210,7 @@ release_all_wakeup (GstPoll * set)
/* try to remove all pending control messages */
if (g_atomic_int_compare_and_exchange (&set->control_pending, old, 0)) {
/* we managed to remove all messages, read the control socket */
result = RELEASE_EVENT (set);
(void) RELEASE_EVENT (set);
break;
}
}

View file

@ -77,9 +77,6 @@
#include <gobject/gvaluecollector.h>
#include <string.h>
GST_DEBUG_CATEGORY_STATIC (gst_tag_interface_debug);
#define GST_CAT_DEFAULT tag_tag_interface_debug
static GQuark gst_tag_key;
typedef struct
@ -108,9 +105,6 @@ gst_tag_setter_get_type (void)
NULL
};
GST_DEBUG_CATEGORY_INIT (gst_tag_interface_debug, "GstTagInterface", 0,
"interfaces for tagging");
_type = g_type_register_static (G_TYPE_INTERFACE, "GstTagSetter",
&tag_setter_info, 0);

View file

@ -99,7 +99,7 @@ typedef enum {
*
* Send a broadcast signal to all waiting task conds
*/
#define GST_TASK_BROADCAST(task) g_cond_breadcast(GST_TASK_GET_COND (task))
#define GST_TASK_BROADCAST(task) g_cond_broadcast(GST_TASK_GET_COND (task))
/**
* GST_TASK_GET_LOCK:

View file

@ -2331,7 +2331,7 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
/* ERRORS */
preroll_failed:
{
GST_DEBUG_OBJECT (sink, "preroll failed %d", ret);
GST_DEBUG_OBJECT (sink, "preroll failed: %s", gst_flow_get_name (ret));
return ret;
}
}

View file

@ -59,7 +59,7 @@
* #GstBaseSrcClass.is_seekable() returns %TRUE.
* </para></listitem>
* <listitem><para>
* #GstBaseSrc:Class.query() can convert all supported seek formats to the
* #GstBaseSrcClass.query() can convert all supported seek formats to the
* internal format as set with gst_base_src_set_format().
* </para></listitem>
* <listitem><para>
@ -565,7 +565,7 @@ gst_base_src_is_live (GstBaseSrc * src)
* for sending NEW_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 #GstBaseSrc.is_seekable() returns TRUE.
* operate in pull mode if the #GstBaseSrcClass.is_seekable() returns TRUE.
*
* This function must only be called in states < %GST_STATE_PAUSED.
*
@ -1737,7 +1737,7 @@ gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
break;
}
default:
result = TRUE;
result = FALSE;
break;
}
return result;
@ -2614,7 +2614,8 @@ gst_base_src_default_negotiate (GstBaseSrc * basesrc)
GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
if (peercaps) {
/* get intersection */
caps = gst_caps_intersect (thiscaps, peercaps);
caps =
gst_caps_intersect_full (peercaps, thiscaps, GST_CAPS_INTERSECT_FIRST);
GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
gst_caps_unref (peercaps);
} else {

View file

@ -129,8 +129,8 @@ struct _GstBaseSrc {
* @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_WRONG_STATE. Any
* future create() function call should also return GST_FLOW_WRONG_STATE
* until the unlock_stop() function has been called.
* future @create<!-- -->() function call should also return GST_FLOW_WRONG_STATE
* until the @unlock_stop<!-- -->() function has been called.
* @unlock_stop: Clear the previous unlock request. Subclasses should clear
* any state they set during unlock(), such as clearing command queues.
* @event: Override this to implement custom event handling.

View file

@ -686,7 +686,8 @@ gst_base_transform_getcaps (GstPad * pad)
/* and filter against the template of this pad */
templ = gst_pad_get_pad_template_caps (pad);
GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
temp = gst_caps_intersect (caps, 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);
/* this is what we can do */

View file

@ -143,6 +143,7 @@ struct _GstBaseTransform {
/**
* GstBaseTransformClass:
* @parent_class: Element parent class
* @transform_caps: Optional. Given the pad in this direction and the given
* caps, what caps are allowed on the other pad in this
* element ?

View file

@ -230,7 +230,8 @@ gst_byte_reader_get_data_unchecked (GstByteReader * reader, guint size)
static inline guint8 *
gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size)
{
return g_memdup (gst_byte_reader_get_data_unchecked (reader, size), size);
gconstpointer data = gst_byte_reader_get_data_unchecked (reader, size);
return (guint8 *) g_memdup (data, size);
}
/* Unchecked variants that should not be used */

View file

@ -181,7 +181,7 @@ _gst_byte_writer_next_pow2 (guint n)
static inline gboolean
_gst_byte_writer_ensure_free_space_inline (GstByteWriter * writer, guint size)
{
guint8 *data;
gpointer data;
if (G_LIKELY (size <= writer->alloc_size - writer->parent.byte))
return TRUE;
@ -195,7 +195,7 @@ _gst_byte_writer_ensure_free_space_inline (GstByteWriter * writer, guint size)
if (G_UNLIKELY (data == NULL))
return FALSE;
writer->parent.data = data;
writer->parent.data = (guint8 *) data;
return TRUE;
}

View file

@ -166,9 +166,9 @@ gst_collect_pads_finalize (GObject * object)
*
* Create a new instance of #GstCollectPads.
*
* Returns: (transfer full): a new #GstCollectPads, or NULL in case of an error.
*
* MT safe.
*
* Returns: (transfer full): a new #GstCollectPads, or NULL in case of an error.
*/
GstCollectPads *
gst_collect_pads_new (void)
@ -262,10 +262,10 @@ unref_data (GstCollectData * data)
* This function calls gst_collect_pads_add_pad_full() passing a value of NULL
* for destroy_notify.
*
* MT safe.
*
* Returns: a new #GstCollectData to identify the new pad. Or NULL
* if wrong parameters are supplied.
*
* MT safe.
*/
GstCollectData *
gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
@ -297,12 +297,12 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
* The pad will be automatically activated in push mode when @pads is
* started.
*
* MT safe.
*
* Since: 0.10.12
*
* Returns: a new #GstCollectData to identify the new pad. Or NULL
* if wrong parameters are supplied.
*
* MT safe.
*/
GstCollectData *
gst_collect_pads_add_pad_full (GstCollectPads * pads, GstPad * pad, guint size,
@ -365,7 +365,7 @@ find_pad (GstCollectData * data, GstPad * pad)
* @user_data: (closure): 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 #GstCollectDataClipFunction for more info.
* on a pad managed by @pads. See #GstCollectPadsClipFunction for more info.
*
* Since: 0.10.26
*/
@ -395,9 +395,9 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads,
*
* The pad will be deactivated automatically when @pads is stopped.
*
* Returns: %TRUE if the pad could be removed.
*
* MT safe.
*
* Returns: %TRUE if the pad could be removed.
*/
gboolean
gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
@ -480,9 +480,9 @@ unknown_pad:
*
* This function is currently not implemented.
*
* Returns: %TRUE if the pad is active.
*
* MT safe.
*
* Returns: %TRUE if the pad is active.
*/
gboolean
gst_collect_pads_is_active (GstCollectPads * pads, GstPad * pad)
@ -506,9 +506,9 @@ gst_collect_pads_is_active (GstCollectPads * pads, GstPad * pad)
*
* This function is currently not implemented.
*
* Returns: #GstFlowReturn of the operation.
*
* MT safe.
*
* Returns: #GstFlowReturn of the operation.
*/
GstFlowReturn
gst_collect_pads_collect (GstCollectPads * pads)
@ -532,9 +532,9 @@ gst_collect_pads_collect (GstCollectPads * pads)
*
* This function is currently not implemented.
*
* Returns: #GstFlowReturn of the operation.
*
* MT safe.
*
* Returns: #GstFlowReturn of the operation.
*/
GstFlowReturn
gst_collect_pads_collect_range (GstCollectPads * pads, guint64 offset,
@ -741,10 +741,10 @@ gst_collect_pads_stop (GstCollectPads * pads)
* should be called with the @pads LOCK held, such as in the callback
* handler.
*
* MT safe.
*
* Returns: (transfer full): The buffer in @data or NULL if no buffer is queued.
* should unref the buffer after usage.
*
* MT safe.
*/
GstBuffer *
gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data)
@ -775,10 +775,10 @@ gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data)
*
* Free-function: gst_buffer_unref
*
* MT safe.
*
* Returns: (transfer full): The buffer in @data or NULL if no buffer was
* queued. You should unref the buffer after usage.
*
* MT safe.
*/
GstBuffer *
gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data)
@ -826,10 +826,10 @@ gst_collect_pads_clear (GstCollectPads * pads, GstCollectData * data)
* This function should be called with @pads 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.
*
* MT safe.
*/
/* FIXME, we can do this in the _chain functions */
guint
@ -897,9 +897,9 @@ not_filled:
* that requested. A return of NULL signals that the pad is end-of-stream.
* Unref the buffer with gst_buffer_unref() after use.
*
* Since: 0.10.18
*
* MT safe.
*
* Since: 0.10.18
*/
GstBuffer *
gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
@ -939,13 +939,13 @@ gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
*
* Free-function: gst_buffer_unref
*
* MT safe.
*
* Returns: (transfer full): a #GstBuffer. 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.
*
* Since: 0.10.18
*
* MT safe.
*/
GstBuffer *
gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data,
@ -970,10 +970,10 @@ gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data,
* This function should be called with @pads 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.
*
* MT safe.
*/
guint
gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,

View file

@ -573,7 +573,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
\
GSequenceIter *iter; \
GstControlPoint *cp; \
GstClockTime x_prev, x, x_next; \
GstClockTime x, x_next; \
g##vtype y_prev, y, y_next; \
\
/* Fill linear system of equations */ \
@ -592,7 +592,6 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
\
for (i = 1; i < n-1; i++) { \
/* Shuffle x and y values */ \
x_prev = x; \
y_prev = y; \
x = x_next; \
y = y_next; \

View file

@ -764,11 +764,11 @@ gst_file_src_create_mmap (GstFileSrc * src, guint64 offset, guint length,
/* if we need to touch the buffer (to bring it into memory), do so */
if (src->touch) {
volatile guchar *p = GST_BUFFER_DATA (buf), c;
volatile guchar *p = GST_BUFFER_DATA (buf);
/* read first byte of each page */
for (i = 0; i < GST_BUFFER_SIZE (buf); i += src->pagesize)
c = p[i];
(void) p[i];
}
/* we're done, return the buffer */

View file

@ -5,6 +5,7 @@
* Copyright (C) 2007 Wim Taymans <wim.taymans@gmail.com>
* Copyright (C) 2007 Andy Wingo <wingo@pobox.com>
* Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.com>)
* Copyright (C) 2011 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
@ -70,6 +71,14 @@ static GStaticRecMutex notify_mutex = G_STATIC_REC_MUTEX_INIT;
#define NOTIFY_MUTEX_UNLOCK() g_static_rec_mutex_unlock (&notify_mutex)
#endif
#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock)
#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond)
#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \
GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel)))
static GstStaticPadTemplate gst_input_selector_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink%d",
GST_PAD_SINK,
@ -137,8 +146,11 @@ struct _GstSelectorPad
GstPad parent;
gboolean active; /* when buffer have passed the pad */
gboolean pushed; /* when buffer was pushed downstream since activation */
gboolean eos; /* when EOS has been received */
gboolean eos_sent; /* when EOS was sent downstream */
gboolean discont; /* after switching we create a discont */
gboolean flushing; /* set after flush-start and before flush-stop */
gboolean always_ok;
GstSegment segment; /* the current segment on the pad */
GstTagList *tags; /* last tags received on the pad */
@ -329,9 +341,12 @@ gst_selector_pad_reset (GstSelectorPad * pad)
{
GST_OBJECT_LOCK (pad);
pad->active = FALSE;
pad->pushed = FALSE;
pad->eos = FALSE;
pad->eos_sent = FALSE;
pad->segment_pending = FALSE;
pad->discont = FALSE;
pad->flushing = FALSE;
gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_UNLOCK (pad);
}
@ -385,7 +400,11 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
/* FIXME, flush out the waiter */
/* Unblock the pad if it's waiting */
GST_INPUT_SELECTOR_LOCK (sel);
selpad->flushing = TRUE;
GST_INPUT_SELECTOR_BROADCAST (sel);
GST_INPUT_SELECTOR_UNLOCK (sel);
break;
case GST_EVENT_FLUSH_STOP:
GST_INPUT_SELECTOR_LOCK (sel);
@ -448,6 +467,25 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
}
case GST_EVENT_EOS:
selpad->eos = TRUE;
if (forward) {
selpad->eos_sent = TRUE;
} else {
GstSelectorPad *tmp;
/* If the active sinkpad is in EOS state but EOS
* was not sent downstream this means that the pad
* got EOS before it was set as active pad and that
* the previously active pad got EOS after it was
* active
*/
GST_INPUT_SELECTOR_LOCK (sel);
active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
tmp = GST_SELECTOR_PAD (active_sinkpad);
forward = (tmp->eos && !tmp->eos_sent);
tmp->eos_sent = TRUE;
GST_INPUT_SELECTOR_UNLOCK (sel);
}
GST_DEBUG_OBJECT (pad, "received EOS");
break;
default:
@ -537,12 +575,14 @@ done:
/* ERRORS */
not_active:
{
gboolean active_pad_pushed = GST_SELECTOR_PAD_CAST (active_sinkpad)->pushed;
GST_INPUT_SELECTOR_UNLOCK (sel);
/* unselected pad, perform fallback alloc or return unlinked when
* asked */
GST_OBJECT_LOCK (selpad);
if (selpad->always_ok) {
if (selpad->always_ok || !active_pad_pushed) {
GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation");
*buf = NULL;
result = GST_FLOW_OK;
@ -559,9 +599,9 @@ not_active:
/* must be called with the SELECTOR_LOCK, will block while the pad is blocked
* or return TRUE when flushing */
static gboolean
gst_input_selector_wait (GstInputSelector * self, GstPad * pad)
gst_input_selector_wait (GstInputSelector * self, GstSelectorPad * pad)
{
while (self->blocked && !self->flushing) {
while (self->blocked && !self->flushing && !pad->flushing) {
/* we can be unlocked here when we are shutting down (flushing) or when we
* get unblocked */
GST_INPUT_SELECTOR_WAIT (self);
@ -588,7 +628,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
GST_INPUT_SELECTOR_LOCK (sel);
/* wait or check for flushing */
if (gst_input_selector_wait (sel, pad))
if (gst_input_selector_wait (sel, selpad))
goto flushing;
GST_LOG_OBJECT (pad, "getting active pad");
@ -675,6 +715,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
}
res = gst_pad_push (sel->srcpad, buf);
selpad->pushed = TRUE;
done:
gst_object_unref (sel);
@ -683,6 +724,8 @@ done:
/* dropped buffers */
ignore:
{
gboolean active_pad_pushed = GST_SELECTOR_PAD_CAST (active_sinkpad)->pushed;
GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf);
/* when we drop a buffer, we're creating a discont on this pad */
selpad->discont = TRUE;
@ -691,7 +734,7 @@ ignore:
/* figure out what to return upstream */
GST_OBJECT_LOCK (selpad);
if (selpad->always_ok)
if (selpad->always_ok || !active_pad_pushed)
res = GST_FLOW_OK;
else
res = GST_FLOW_NOT_LINKED;
@ -1032,6 +1075,8 @@ gst_input_selector_set_active_pad (GstInputSelector * self,
gst_segment_set_stop (&self->segment, stop_time);
self->pending_close = TRUE;
}
if (old)
old->pushed = FALSE;
if (new && new->active && start_time >= 0) {
GST_DEBUG_OBJECT (self, "setting start_time to %" GST_TIME_FORMAT,
@ -1040,6 +1085,8 @@ gst_input_selector_set_active_pad (GstInputSelector * self,
gst_segment_set_start (&new->segment, start_time);
new->segment_pending = TRUE;
}
if (new)
new->pushed = FALSE;
active_pad_p = &self->active_sinkpad;
gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad));

View file

@ -2,6 +2,7 @@
* Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
* Copyright (C) 2007 Jan Schmidt <jan@fluendo.com>
* Copyright (C) 2007 Wim Taymans <wim@fluendo.com>
* Copyright (C) 2011 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* gstmultiqueue.c:
*
@ -148,6 +149,7 @@ struct _GstSingleQueue
GstDataQueueSize max_size, extra_size;
GstClockTime cur_time;
gboolean is_eos;
gboolean flushing;
/* Protected by global lock */
guint32 nextid; /* ID of the next object waiting to be pushed */
@ -254,6 +256,8 @@ static void gst_multi_queue_get_property (GObject * object,
static GstPad *gst_multi_queue_request_new_pad (GstElement * element,
GstPadTemplate * temp, const gchar * name);
static void gst_multi_queue_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_multi_queue_change_state (GstElement *
element, GstStateChange transition);
static void gst_multi_queue_loop (GstPad * pad);
@ -398,6 +402,8 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
GST_DEBUG_FUNCPTR (gst_multi_queue_request_new_pad);
gstelement_class->release_pad =
GST_DEBUG_FUNCPTR (gst_multi_queue_release_pad);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_multi_queue_change_state);
}
static void
@ -420,7 +426,6 @@ gst_multi_queue_init (GstMultiQueue * mqueue, GstMultiQueueClass * klass)
mqueue->counter = 1;
mqueue->highid = -1;
mqueue->nextnotlinked = -1;
mqueue->qlock = g_mutex_new ();
}
@ -649,6 +654,56 @@ gst_multi_queue_release_pad (GstElement * element, GstPad * pad)
gst_single_queue_free (sq);
}
static GstStateChangeReturn
gst_multi_queue_change_state (GstElement * element, GstStateChange transition)
{
GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
GstSingleQueue *sq = NULL;
GstStateChangeReturn result;
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:{
GList *tmp;
/* Set all pads to non-flushing */
GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
sq = (GstSingleQueue *) tmp->data;
sq->flushing = FALSE;
}
GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
break;
}
case GST_STATE_CHANGE_PAUSED_TO_READY:{
GList *tmp;
/* Un-wait all waiting pads */
GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
sq = (GstSingleQueue *) tmp->data;
sq->flushing = TRUE;
g_cond_signal (sq->turn);
}
GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
break;
}
default:
break;
}
result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
default:
break;
}
return result;
}
static gboolean
gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
{
@ -661,6 +716,8 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
sq->srcresult = GST_FLOW_WRONG_STATE;
gst_data_queue_set_flushing (sq->queue, TRUE);
sq->flushing = TRUE;
/* wake up non-linked task */
GST_LOG_OBJECT (mq, "SingleQueue %d : waking up eventually waiting task",
sq->id);
@ -685,6 +742,8 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
sq->last_oldid = G_MAXUINT32;
gst_data_queue_set_flushing (sq->queue, FALSE);
sq->flushing = FALSE;
GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id);
result =
gst_pad_start_task (sq->srcpad, (GstTaskFunction) gst_multi_queue_loop,
@ -1016,7 +1075,7 @@ gst_multi_queue_loop (GstPad * pad)
GstMultiQueueItem *item;
GstDataQueueItem *sitem;
GstMultiQueue *mq;
GstMiniObject *object;
GstMiniObject *object = NULL;
guint32 newid;
GstFlowReturn result;
@ -1025,6 +1084,9 @@ gst_multi_queue_loop (GstPad * pad)
GST_DEBUG_OBJECT (mq, "SingleQueue %d : trying to pop an object", sq->id);
if (sq->flushing)
goto out_flushing;
/* Get something from the queue, blocking until that happens, or we get
* flushed */
if (!(gst_data_queue_pop (sq->queue, &sitem)))
@ -1077,6 +1139,11 @@ gst_multi_queue_loop (GstPad * pad)
g_cond_wait (sq->turn, mq->qlock);
mq->numwaiting--;
if (sq->flushing) {
GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
goto out_flushing;
}
GST_DEBUG_OBJECT (mq, "queue %d woken from sleeping for not-linked "
"wakeup with newid %u and highid %u", sq->id, newid, mq->highid);
}
@ -1094,12 +1161,16 @@ gst_multi_queue_loop (GstPad * pad)
GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
}
if (sq->flushing)
goto out_flushing;
GST_LOG_OBJECT (mq, "BEFORE PUSHING sq->srcresult: %s",
gst_flow_get_name (sq->srcresult));
/* Try to push out the new object */
result = gst_single_queue_push_one (mq, sq, object);
sq->srcresult = result;
object = NULL;
if (result != GST_FLOW_OK && result != GST_FLOW_NOT_LINKED
&& result != GST_FLOW_UNEXPECTED)
@ -1113,6 +1184,9 @@ gst_multi_queue_loop (GstPad * pad)
out_flushing:
{
if (object)
gst_mini_object_unref (object);
/* Need to make sure wake up any sleeping pads when we exit */
GST_MULTI_QUEUE_MUTEX_LOCK (mq);
compute_high_id (mq);
@ -1159,7 +1233,7 @@ gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer)
goto was_eos;
/* Get a unique incrementing id */
curid = mq->counter++;
curid = g_atomic_int_exchange_and_add ((gint *) & mq->counter, 1);
GST_LOG_OBJECT (mq, "SingleQueue %d : about to enqueue buffer %p with id %d",
sq->id, buffer, curid);
@ -1264,9 +1338,8 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
if (sq->is_eos)
goto was_eos;
/* Get an unique incrementing id. protected with the STREAM_LOCK, unserialized
* events already got pushed and don't end up in the queue. */
curid = mq->counter++;
/* Get an unique incrementing id. */
curid = g_atomic_int_exchange_and_add ((gint *) & mq->counter, 1);
item = gst_multi_queue_event_item_new ((GstMiniObject *) event, curid);
@ -1664,6 +1737,7 @@ gst_single_queue_new (GstMultiQueue * mqueue)
(GstDataQueueFullCallback) single_queue_overrun_cb,
(GstDataQueueEmptyCallback) single_queue_underrun_cb, sq);
sq->is_eos = FALSE;
sq->flushing = FALSE;
gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME);
gst_segment_init (&sq->src_segment, GST_FORMAT_TIME);

View file

@ -63,15 +63,13 @@ struct _GstMultiQueue {
gboolean buffering;
gint percent;
guint32 counter; /* incoming object counter, protected with STREAM_LOCK */
guint32 counter; /* incoming object counter, use atomic accesses */
guint32 highid; /* contains highest id of last outputted object */
GMutex * qlock; /* Global queue lock (vs object lock or individual */
/* queues lock). Protects nbqueues, queues, global */
/* GstMultiQueueSize, counter and highid */
gint nextnotlinked; /* ID of the next queue not linked (-1 : none) */
gint numwaiting; /* number of not-linked pads waiting */
};

View file

@ -39,17 +39,26 @@ G_BEGIN_DECLS
#define GST_IS_QUEUE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE))
enum {
typedef struct _GstQueue GstQueue;
typedef struct _GstQueueSize GstQueueSize;
typedef enum _GstQueueLeaky GstQueueLeaky;
typedef struct _GstQueueClass GstQueueClass;
/**
* GstQueueLeaky:
* @GST_QUEUE_NO_LEAK: Not Leaky
* @GST_QUEUE_LEAK_UPSTREAM: Leaky on upstream (new buffers)
* @GST_QUEUE_LEAK_DOWNSTREAM: Leaky on downstream (old buffers)
*
* Buffer dropping scheme to avoid the queue to block when full.
*/
enum _GstQueueLeaky {
GST_QUEUE_NO_LEAK = 0,
GST_QUEUE_LEAK_UPSTREAM = 1,
GST_QUEUE_LEAK_DOWNSTREAM = 2
};
typedef struct _GstQueue GstQueue;
typedef struct _GstQueueSize GstQueueSize;
typedef struct _GstQueueClass GstQueueClass;
/**
/*
* GstQueueSize:
* @buffers: number of buffers
* @bytes: number of bytes

View file

@ -369,7 +369,7 @@ gst_queue2_class_init (GstQueue2Class * klass)
g_param_spec_uint64 ("ring-buffer-max-size",
"Max. ring buffer size (bytes)",
"Max. amount of data in the ring buffer (bytes, 0 = disabled",
0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE,
0, G_MAXUINT64, DEFAULT_RING_BUFFER_MAX_SIZE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* set several parent class virtual functions */

View file

@ -50,7 +50,7 @@ LIBSABI_CHECKS = libs/libsabi
endif
if HAVE_CXX
CXX_CHECKS = gst/gstcpp
CXX_CHECKS = gst/gstcpp libs/gstlibscpp
else
CXX_CHECKS =
endif
@ -173,6 +173,8 @@ LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_MAJORMINOR@.la \
gst_gstcpp_SOURCES = gst/gstcpp.cc
libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc
gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS)
libs_gdp_SOURCES = \

View file

@ -728,6 +728,90 @@ GST_START_TEST (test_intersect2)
GST_END_TEST;
GST_START_TEST (test_intersect_zigzag)
{
GstCaps *caps1, *caps2, *icaps, *result;
/* tests if caps order is maintained */
caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D");
caps2 = gst_caps_from_string ("format/D; format/A; format/B; format/C");
icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG);
result = gst_caps_from_string ("format/B; format/A; format/D; format/C");
GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
fail_if (gst_caps_is_empty (icaps));
fail_unless (gst_caps_is_equal (icaps, result));
gst_caps_unref (icaps);
gst_caps_unref (result);
icaps = gst_caps_intersect_full (caps2, caps1, GST_CAPS_INTERSECT_FIRST);
result = gst_caps_from_string ("format/A; format/B; format/D; format/C");
GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
fail_if (gst_caps_is_empty (icaps));
fail_unless (gst_caps_is_equal (icaps, result));
gst_caps_unref (icaps);
gst_caps_unref (result);
gst_caps_unref (caps1);
gst_caps_unref (caps2);
}
GST_END_TEST;
GST_START_TEST (test_intersect_first)
{
GstCaps *caps1, *caps2, *icaps, *result;
/* tests if caps order is maintained */
caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D");
caps2 = gst_caps_from_string ("format/C; format/D; format/A");
icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_FIRST);
result = gst_caps_from_string ("format/A; format/C; format/D");
GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
fail_if (gst_caps_is_empty (icaps));
fail_unless (gst_caps_is_equal (icaps, result));
gst_caps_unref (caps1);
gst_caps_unref (caps2);
gst_caps_unref (icaps);
gst_caps_unref (result);
}
GST_END_TEST;
GST_START_TEST (test_intersect_first2)
{
GstCaps *caps1, *caps2, *icaps, *result;
/* tests if caps order is maintained */
caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D");
caps2 = gst_caps_from_string ("format/D; format/A; format/B; format/C");
icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_FIRST);
result = gst_caps_from_string ("format/A; format/B; format/C; format/D");
GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
fail_if (gst_caps_is_empty (icaps));
fail_unless (gst_caps_is_equal (icaps, result));
gst_caps_unref (icaps);
gst_caps_unref (result);
icaps = gst_caps_intersect_full (caps2, caps1, GST_CAPS_INTERSECT_FIRST);
result = gst_caps_from_string ("format/D; format/A; format/B; format/C");
GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
fail_if (gst_caps_is_empty (icaps));
fail_unless (gst_caps_is_equal (icaps, result));
gst_caps_unref (icaps);
gst_caps_unref (result);
gst_caps_unref (caps1);
gst_caps_unref (caps2);
}
GST_END_TEST;
static gboolean
_caps_is_fixed_foreach (GQuark field_id, const GValue * value, gpointer unused)
{
@ -834,6 +918,9 @@ gst_caps_suite (void)
tcase_add_test (tc_chain, test_merge_subset);
tcase_add_test (tc_chain, test_intersect);
tcase_add_test (tc_chain, test_intersect2);
tcase_add_test (tc_chain, test_intersect_zigzag);
tcase_add_test (tc_chain, test_intersect_first);
tcase_add_test (tc_chain, test_intersect_first2);
tcase_add_test (tc_chain, test_normalize);
tcase_add_test (tc_chain, test_broken);

View file

@ -8,6 +8,7 @@ bytewriter
gdp
collectpads
controller
gstlibscpp
gstnetclientclock
gstnettimeprovider
libsabi

View file

@ -0,0 +1,75 @@
/* GStreamer
* Copyright (C) 2011 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gst/gst.h>
#include <gst/check/gstcheck.h>
#include <gst/base/gstadapter.h>
#include <gst/base/gstbasesink.h>
#include <gst/base/gstbasesrc.h>
#include <gst/base/gstbasetransform.h>
#include <gst/base/gstbitreader.h>
#include <gst/base/gstbytereader.h>
#include <gst/base/gstbytewriter.h>
#include <gst/base/gstcollectpads.h>
#include <gst/base/gstdataqueue.h>
#include <gst/base/gstpushsrc.h>
#include <gst/base/gsttypefindhelper.h>
#include <gst/controller/gstcontroller.h>
#include <gst/controller/gstcontrollerprivate.h>
#include <gst/controller/gstcontrolsource.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
#include <gst/controller/gstinterpolationcontrolsourceprivate.h>
#include <gst/controller/gstlfocontrolsource.h>
#include <gst/controller/gstlfocontrolsourceprivate.h>
#include <gst/dataprotocol/dataprotocol.h>
#include <gst/net/gstnetclientclock.h>
#include <gst/net/gstnet.h>
#include <gst/net/gstnettimepacket.h>
#include <gst/net/gstnettimeprovider.h>
/* we mostly just want to make sure that our library headers don't
* contain anything a C++ compiler might not like */
GST_START_TEST (test_nothing)
{
gst_init (NULL, NULL);
}
GST_END_TEST;
static Suite *
libscpp_suite (void)
{
Suite *s = suite_create ("GstLibsCpp");
TCase *tc_chain = tcase_create ("C++ libs header tests");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_nothing);
return s;
}
GST_CHECK_MAIN (libscpp);

View file

@ -179,6 +179,8 @@ EXPORTS
gst_caps_get_size
gst_caps_get_structure
gst_caps_intersect
gst_caps_intersect_full
gst_caps_intersect_mode_get_type
gst_caps_is_always_compatible
gst_caps_is_any
gst_caps_is_empty