mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
Merge branch 'master' into 0.11-fdo
Conflicts: gst/gst.c libs/gst/base/gstcollectpads.c
This commit is contained in:
commit
a12ede3fb1
34 changed files with 531 additions and 112 deletions
|
@ -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
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 6aec6b9716c184c60c4bc6a5916a2471cfa8c8cd
|
||||
Subproject commit 1ccbe098d6379612fcef09f4000da23585af980a
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -149,6 +149,7 @@ GST_INPUT_SELECTOR_WAIT
|
|||
<FILE>element-queue</FILE>
|
||||
<TITLE>queue</TITLE>
|
||||
GstQueue
|
||||
GstQueueLeaky
|
||||
<SUBSECTION Standard>
|
||||
GstQueueClass
|
||||
GST_QUEUE
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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. */
|
||||
|
|
120
gst/gstcaps.c
120
gst/gstcaps.c
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 (¬ify_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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 = \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
1
tests/check/libs/.gitignore
vendored
1
tests/check/libs/.gitignore
vendored
|
@ -8,6 +8,7 @@ bytewriter
|
|||
gdp
|
||||
collectpads
|
||||
controller
|
||||
gstlibscpp
|
||||
gstnetclientclock
|
||||
gstnettimeprovider
|
||||
libsabi
|
||||
|
|
75
tests/check/libs/gstlibscpp.cc
Normal file
75
tests/check/libs/gstlibscpp.cc
Normal 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);
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue