diff --git a/autogen.sh b/autogen.sh index fd523618f4..c0cd19e54c 100755 --- a/autogen.sh +++ b/autogen.sh @@ -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" diff --git a/common b/common index 6aec6b9716..1ccbe098d6 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 6aec6b9716c184c60c4bc6a5916a2471cfa8c8cd +Subproject commit 1ccbe098d6379612fcef09f4000da23585af980a diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am index 4172285e7c..2cda7f51c5 100644 --- a/docs/libs/Makefile.am +++ b/docs/libs/Makefile.am @@ -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. diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 0e44c57f2a..9fa051f680 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -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. diff --git a/docs/plugins/gstreamer-plugins-sections.txt b/docs/plugins/gstreamer-plugins-sections.txt index 1854112140..742fdf9dad 100644 --- a/docs/plugins/gstreamer-plugins-sections.txt +++ b/docs/plugins/gstreamer-plugins-sections.txt @@ -149,6 +149,7 @@ GST_INPUT_SELECTOR_WAIT element-queue queue GstQueue +GstQueueLeaky GstQueueClass GST_QUEUE diff --git a/gst/gst.c b/gst/gst.c index 1cc273ee01..5227bf2b6f 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -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"); diff --git a/gst/gstbin.c b/gst/gstbin.c index 9641b8b0f3..1764caef3b 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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. */ diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 9b47f6d27a..09724d0b24 100644 --- a/gst/gstcaps.c +++ b/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 diff --git a/gst/gstcaps.h b/gst/gstcaps.h index fd6c411fbb..a3b30a2fb9 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -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, diff --git a/gst/gstelement.h b/gst/gstelement.h index 3bd798de0e..f7303a4f38 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -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 diff --git a/gst/gstevent.h b/gst/gstevent.h index a8b35d3d0d..3e5cbe73ce 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -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. diff --git a/gst/gstpoll.c b/gst/gstpoll.c index cbc3904d94..ba9fdc8bca 100644 --- a/gst/gstpoll.c +++ b/gst/gstpoll.c @@ -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; } } diff --git a/gst/gsttagsetter.c b/gst/gsttagsetter.c index 05dbbab439..5a5f967f48 100644 --- a/gst/gsttagsetter.c +++ b/gst/gsttagsetter.c @@ -77,9 +77,6 @@ #include #include -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); diff --git a/gst/gsttask.h b/gst/gsttask.h index ed48b0bfb9..21784b73ee 100644 --- a/gst/gsttask.h +++ b/gst/gsttask.h @@ -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: diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index ebd1d06dc6..356aa41343 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -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; } } diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 74597ae058..efb8400052 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -59,7 +59,7 @@ * #GstBaseSrcClass.is_seekable() returns %TRUE. * * - * #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(). * * @@ -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 { diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h index 2ccea4f5e1..a492d105bb 100644 --- a/libs/gst/base/gstbasesrc.h +++ b/libs/gst/base/gstbasesrc.h @@ -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. diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index 19087c2dcc..296ba94cd8 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -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 */ diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h index eaa56d3287..cdab570426 100644 --- a/libs/gst/base/gstbasetransform.h +++ b/libs/gst/base/gstbasetransform.h @@ -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 ? @@ -170,7 +171,7 @@ struct _GstBaseTransform { * Transform the incoming buffer in-place. * @event: Optional. * Event handler on the sink pad. This function should return - * TRUE if the base class should forward the event. + * TRUE if the base class should forward the event. * @src_event: Optional. * Event handler on the source pad. * @passthrough_on_same_caps: If set to TRUE, passthrough mode will be diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h index 440c80321a..9c3c4f46a6 100644 --- a/libs/gst/base/gstbytereader.h +++ b/libs/gst/base/gstbytereader.h @@ -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 */ diff --git a/libs/gst/base/gstbytewriter.h b/libs/gst/base/gstbytewriter.h index 9f369bed10..7cc68d25e3 100644 --- a/libs/gst/base/gstbytewriter.h +++ b/libs/gst/base/gstbytewriter.h @@ -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; } diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c index e9a89e6d97..ceba51f71a 100644 --- a/libs/gst/base/gstcollectpads.c +++ b/libs/gst/base/gstcollectpads.c @@ -28,7 +28,7 @@ * * * Collectpads are created with gst_collect_pads_new(). A callback should then - * be installed with gst_collect_pads_set_function (). + * be installed with gst_collect_pads_set_function (). * * * Pads are added to the collection with gst_collect_pads_add_pad()/ @@ -52,7 +52,7 @@ * event itself. * * - * Data can also be dequeued in byte units using the gst_collect_pads_available(), + * Data can also be dequeued in byte units using the gst_collect_pads_available(), * gst_collect_pads_read() and gst_collect_pads_flush() calls. * * @@ -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 */ @@ -390,14 +390,14 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads, * @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 + * 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. * - * 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) @@ -502,13 +502,13 @@ gst_collect_pads_is_active (GstCollectPads * pads, GstPad * pad) * @pads: the collectspads to use * * Collect data on all pads. This function is usually called - * from a #GstTask function in an element. + * from a #GstTask function in an element. * * 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) @@ -528,13 +528,13 @@ gst_collect_pads_collect (GstCollectPads * pads) * @length: the length to collect * * Collect data with @offset and @length on all pads. This function - * is typically called in the getrange function of an element. + * is typically called in the getrange function of an element. * * 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, @@ -607,7 +607,7 @@ gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads, } } /* Setting the pads to flushing means that we changed the values which - * are 'protected' by the cookie. We therefore update it to force a + * are 'protected' by the cookie. We therefore update it to force a * recalculation of the current pad status. */ pads->abidata.ABI.pad_cookie++; } @@ -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, @@ -1147,7 +1147,7 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event) gst_pad_event_default (pad, event); /* now unblock the chain function. - * no cond per pad, so they all unblock, + * no cond per pad, so they all unblock, * non-flushing block again */ GST_OBJECT_LOCK (pads); data->abidata.ABI.flushing = TRUE; @@ -1221,7 +1221,7 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event) data->abidata.ABI.new_segment = TRUE; - /* we must not forward this event since multiple segments will be + /* we must not forward this event since multiple segments will be * accumulated and this is certainly not what we want. */ gst_event_unref (event); /* FIXME: collect-pads based elements need to create their own newsegment @@ -1263,7 +1263,7 @@ pad_removed: * 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 + * collected */ static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer) @@ -1353,7 +1353,7 @@ gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer) /* 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. + * because we still hold the STREAM_LOCK. */ GST_COLLECT_PADS_WAIT (pads); diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c index c3a427482d..54ff60e1a0 100644 --- a/libs/gst/controller/gstinterpolation.c +++ b/libs/gst/controller/gstinterpolation.c @@ -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; \ diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index a834037aba..7df201e16e 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -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 */ diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c index 5f907d7f70..2d31d89408 100644 --- a/plugins/elements/gstinputselector.c +++ b/plugins/elements/gstinputselector.c @@ -5,6 +5,7 @@ * Copyright (C) 2007 Wim Taymans * Copyright (C) 2007 Andy Wingo * Copyright (C) 2008 Nokia Corporation. (contact ) + * Copyright (C) 2011 Sebastian Dröge * * 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)); diff --git a/plugins/elements/gstmultiqueue.c b/plugins/elements/gstmultiqueue.c index 0adf6a3b40..4a4bb37a4e 100644 --- a/plugins/elements/gstmultiqueue.c +++ b/plugins/elements/gstmultiqueue.c @@ -2,6 +2,7 @@ * Copyright (C) 2006 Edward Hervey * Copyright (C) 2007 Jan Schmidt * Copyright (C) 2007 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge * * 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); diff --git a/plugins/elements/gstmultiqueue.h b/plugins/elements/gstmultiqueue.h index ec47601d08..b9c28cd442 100644 --- a/plugins/elements/gstmultiqueue.h +++ b/plugins/elements/gstmultiqueue.h @@ -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 */ }; diff --git a/plugins/elements/gstqueue.h b/plugins/elements/gstqueue.h index c72bcb790c..6ab861706f 100644 --- a/plugins/elements/gstqueue.h +++ b/plugins/elements/gstqueue.h @@ -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 @@ -115,8 +124,8 @@ struct _GstQueue { gboolean head_needs_discont, tail_needs_discont; gboolean push_newsegment; - - gboolean silent; /* don't emit signals */ + + gboolean silent; /* don't emit signals */ /* whether the first new segment has been applied to src */ gboolean newseg_applied_to_src; diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c index d90a1536b7..a0c065ea41 100644 --- a/plugins/elements/gstqueue2.c +++ b/plugins/elements/gstqueue2.c @@ -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 */ @@ -766,7 +766,7 @@ apply_buffer (GstQueue2 * queue, GstBuffer * buffer, GstSegment * segment, timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); - /* if no timestamp is set, assume it's continuous with the previous + /* if no timestamp is set, assume it's continuous with the previous * time */ if (timestamp == GST_CLOCK_TIME_NONE) timestamp = segment->last_stop; diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 62a29ffca4..00ca28d0d4 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -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 = \ diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c index d1bbe4bedc..fa160d91dd 100644 --- a/tests/check/gst/gstcaps.c +++ b/tests/check/gst/gstcaps.c @@ -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); diff --git a/tests/check/libs/.gitignore b/tests/check/libs/.gitignore index 64540fdb34..8eb96b413b 100644 --- a/tests/check/libs/.gitignore +++ b/tests/check/libs/.gitignore @@ -8,6 +8,7 @@ bytewriter gdp collectpads controller +gstlibscpp gstnetclientclock gstnettimeprovider libsabi diff --git a/tests/check/libs/gstlibscpp.cc b/tests/check/libs/gstlibscpp.cc new file mode 100644 index 0000000000..23079e8666 --- /dev/null +++ b/tests/check/libs/gstlibscpp.cc @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) 2011 Tim-Philipp Müller + * + * 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 +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* 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); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 6ffaf14a68..f1dd76cf1e 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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