summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <edward.hervey@collabora.co.uk>2011-10-21 10:52:46 +0200
committerEdward Hervey <edward.hervey@collabora.co.uk>2011-10-21 10:52:46 +0200
commitdf6044f7ebdaf0c38217c95b7d9cc5340567d800 (patch)
tree0739ec3a69b104eed7aa97baa1cbc10ff7f5c769
parent5800757369ae90b770cca3ca840c2c607b9b9f21 (diff)
parent905d1fea180dfa8c81486712689bba54639ef472 (diff)
Merging origin/master
Conflicts: gst/gstbin.c gst/gstbus.c gst/gstdebugutils.c gst/gstpad.c libs/gst/base/gstbaseparse.c libs/gst/base/gstbasesrc.c
-rw-r--r--Android.mk2
-rw-r--r--gst/gstbin.c3
-rw-r--r--gst/gstbus.c13
-rw-r--r--gst/gstdebugutils.c108
-rw-r--r--gst/gstmessage.c7
-rw-r--r--gst/gstpad.c40
-rw-r--r--libs/gst/base/gstbaseparse.c149
-rw-r--r--libs/gst/base/gstbaseparse.h13
-rw-r--r--libs/gst/base/gstbasesink.c8
9 files changed, 255 insertions, 88 deletions
diff --git a/Android.mk b/Android.mk
index d9868cab8..10b28a865 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,7 +13,7 @@ GST_BUILT_SOURCES := \
gst/parse/grammar.tab.h \
gst/parse/grammar.tab.c \
gst/parse/grammar.output \
- gst/parse/lex._gst_parse_yy.c \
+ gst/parse/lex.priv_gst_parse_yy.c \
pkgconfig/gstreamer-0.10.pc \
pkgconfig/gstreamer-base-0.10.pc \
pkgconfig/gstreamer-controller-0.10.pc \
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 1168ee75b..815a33b88 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -2689,7 +2689,8 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
gst_event_ref (event);
res &= gst_element_send_event (child, event);
- g_value_reset (&data);
+ GST_LOG_OBJECT (child, "After handling %s event: %d",
+ GST_EVENT_TYPE_NAME (event), res);
break;
}
case GST_ITERATOR_RESYNC:
diff --git a/gst/gstbus.c b/gst/gstbus.c
index 00a361294..a1250511c 100644
--- a/gst/gstbus.c
+++ b/gst/gstbus.c
@@ -481,8 +481,9 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
while ((message = gst_atomic_queue_pop (bus->queue))) {
if (bus->priv->poll)
gst_poll_read_control (bus->priv->poll);
- GST_DEBUG_OBJECT (bus, "got message %p, %s, type mask is %u",
- message, GST_MESSAGE_TYPE_NAME (message), (guint) types);
+ GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u",
+ message, GST_MESSAGE_TYPE_NAME (message),
+ GST_OBJECT_NAME (GST_MESSAGE_SRC (message)), (guint) types);
if ((GST_MESSAGE_TYPE (message) & types) != 0) {
/* exit the loop, we have a message */
goto beach;
@@ -731,7 +732,8 @@ gst_bus_source_dispatch (GSource * source, GSourceFunc callback,
if (!handler)
goto no_handler;
- GST_DEBUG_OBJECT (bus, "source %p calling dispatch with %p", source, message);
+ GST_DEBUG_OBJECT (bus, "source %p calling dispatch with %" GST_PTR_FORMAT,
+ source, message);
keep = handler (bus, message, user_data);
gst_message_unref (message);
@@ -795,6 +797,11 @@ gst_bus_create_watch (GstBus * bus)
source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
sizeof (GstBusSource));
+
+#if GLIB_CHECK_VERSION(2,26,0)
+ g_source_set_name ((GSource *) source, "GStreamer message bus watch");
+#endif
+
source->bus = gst_object_ref (bus);
g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
diff --git a/gst/gstdebugutils.c b/gst/gstdebugutils.c
index ce0647083..d70171904 100644
--- a/gst/gstdebugutils.c
+++ b/gst/gstdebugutils.c
@@ -66,10 +66,10 @@ const gchar spaces[] = {
extern GstClockTime _priv_gst_info_start_time;
static gchar *
-debug_dump_make_object_name (GstObject * element)
+debug_dump_make_object_name (GstObject * obj)
{
- return g_strcanon (g_strdup_printf ("%s_%p", GST_OBJECT_NAME (element),
- element), G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_", '_');
+ return g_strcanon (g_strdup_printf ("%s_%p", GST_OBJECT_NAME (obj), obj),
+ G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_", '_');
}
static gchar *
@@ -205,6 +205,9 @@ debug_dump_element_pad (GstPad * pad, GstElement * element,
/* output target-pad so that it belongs to this element */
if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
if ((target_pad = gst_pad_get_peer (tmp_pad))) {
+ gchar *pad_name, *target_pad_name;
+ const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
+
if ((target_element = gst_pad_get_parent_element (target_pad))) {
target_element_name =
debug_dump_make_object_name (GST_OBJECT (target_element));
@@ -213,10 +216,22 @@ debug_dump_element_pad (GstPad * pad, GstElement * element,
}
debug_dump_pad (target_pad, color_name, target_element_name, details,
out, indent);
+ /* src ghostpad relationship */
+ pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
+ target_pad_name = debug_dump_make_object_name (GST_OBJECT (target_pad));
+ if (dir == GST_PAD_SRC) {
+ fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+ target_element_name, target_pad_name, element_name, pad_name);
+ } else {
+ fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+ element_name, pad_name, target_element_name, target_pad_name);
+ }
+ g_free (target_pad_name);
g_free (target_element_name);
if (target_element)
gst_object_unref (target_element);
gst_object_unref (target_pad);
+ g_free (pad_name);
}
gst_object_unref (tmp_pad);
}
@@ -319,14 +334,13 @@ static void
debug_dump_element_pad_link (GstPad * pad, GstElement * element,
GstDebugGraphDetails details, FILE * out, const gint indent)
{
- GstElement *peer_element, *target_element;
- GstPad *peer_pad, *target_pad, *tmp_pad;
+ GstElement *peer_element;
+ GstPad *peer_pad;
GstCaps *caps, *peer_caps;
gchar *media = NULL;
gchar *media_src = NULL, *media_sink = NULL;
gchar *pad_name, *element_name;
gchar *peer_pad_name, *peer_element_name;
- gchar *target_pad_name, *target_element_name;
const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
if ((peer_pad = gst_pad_get_peer (pad))) {
@@ -373,63 +387,6 @@ debug_dump_element_pad_link (GstPad * pad, GstElement * element,
peer_element_name = g_strdup ("");
}
- if (GST_IS_GHOST_PAD (pad)) {
- if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
- if ((target_pad = gst_pad_get_peer (tmp_pad))) {
- target_pad_name =
- debug_dump_make_object_name (GST_OBJECT (target_pad));
- if ((target_element = gst_pad_get_parent_element (target_pad))) {
- target_element_name =
- debug_dump_make_object_name (GST_OBJECT (target_element));
- } else {
- target_element_name = g_strdup ("");
- }
- /* src ghostpad relationship */
- fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
- target_element_name, target_pad_name, element_name, pad_name);
-
- g_free (target_pad_name);
- g_free (target_element_name);
- if (target_element)
- gst_object_unref (target_element);
- gst_object_unref (target_pad);
- }
- gst_object_unref (tmp_pad);
- }
- }
- if (GST_IS_GHOST_PAD (peer_pad)) {
- if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) {
- if ((target_pad = gst_pad_get_peer (tmp_pad))) {
- target_pad_name =
- debug_dump_make_object_name (GST_OBJECT (target_pad));
- if ((target_element = gst_pad_get_parent_element (target_pad))) {
- target_element_name =
- debug_dump_make_object_name (GST_OBJECT (target_element));
- } else {
- target_element_name = g_strdup ("");
- }
- /* sink ghostpad relationship */
- fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
- peer_element_name, peer_pad_name,
- target_element_name, target_pad_name);
- /* FIXME: we are missing links from the proxy pad
- * theoretically we need to:
- * pad=gst_object_ref(target_pad);
- * goto line 280: if ((peer_pad = gst_pad_get_peer (pad)))
- * as this would be ugly we need to refactor ...
- */
- debug_dump_element_pad_link (target_pad, target_element, details, out,
- indent);
- g_free (target_pad_name);
- g_free (target_element_name);
- if (target_element)
- gst_object_unref (target_element);
- gst_object_unref (target_pad);
- }
- gst_object_unref (tmp_pad);
- }
- }
-
/* pad link */
if (media) {
fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
@@ -583,10 +540,22 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
switch (gst_iterator_next (pad_iter, &item2)) {
case GST_ITERATOR_OK:
pad = g_value_get_object (&item2);
- if (gst_pad_is_linked (pad)
- && gst_pad_get_direction (pad) == GST_PAD_SRC) {
- debug_dump_element_pad_link (pad, element, details, out,
- indent);
+ if (gst_pad_is_linked (pad)) {
+ if (gst_pad_get_direction (pad) == GST_PAD_SRC) {
+ debug_dump_element_pad_link (pad, element, details, out,
+ indent);
+ } else {
+ GstPad *peer_pad = gst_pad_get_peer (pad);
+
+ if (peer_pad) {
+ if (!GST_IS_GHOST_PAD (peer_pad)
+ && GST_IS_PROXY_PAD (peer_pad)) {
+ debug_dump_element_pad_link (peer_pad, NULL, details,
+ out, indent);
+ }
+ gst_object_unref (peer_pad);
+ }
+ }
}
g_value_reset (&item2);
break;
@@ -613,6 +582,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
break;
}
}
+
g_value_unset (&item);
gst_iterator_free (element_iter);
}
@@ -703,8 +673,8 @@ _gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
* to the filename, so that it can be used to take multiple snapshots.
*/
void
-_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
- const gchar * file_name)
+_gst_debug_bin_to_dot_file_with_ts (GstBin * bin,
+ GstDebugGraphDetails details, const gchar * file_name)
{
gchar *ts_file_name = NULL;
GstClockTime elapsed;
diff --git a/gst/gstmessage.c b/gst/gstmessage.c
index 41e7ccce5..7b481ac27 100644
--- a/gst/gstmessage.c
+++ b/gst/gstmessage.c
@@ -177,7 +177,8 @@ _gst_message_free (GstMessage * message)
g_return_if_fail (message != NULL);
- GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p", message);
+ GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p, %s from %s", message,
+ GST_MESSAGE_TYPE_NAME (message), GST_MESSAGE_SRC_NAME (message));
if (GST_MESSAGE_SRC (message)) {
gst_object_unref (GST_MESSAGE_SRC (message));
@@ -205,7 +206,9 @@ _gst_message_copy (GstMessage * message)
GstMessageImpl *copy;
GstStructure *structure;
- GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p", message);
+ GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p, %s from %s", message,
+ GST_MESSAGE_TYPE_NAME (message),
+ GST_OBJECT_NAME (GST_MESSAGE_SRC (message)));
copy = g_slice_new0 (GstMessageImpl);
diff --git a/gst/gstpad.c b/gst/gstpad.c
index 7f859549a..bee078d59 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -1065,6 +1065,19 @@ gst_pad_add_probe (GstPad * pad, GstProbeType mask,
g_return_val_if_fail (mask != 0, 0);
GST_OBJECT_LOCK (pad);
+
+ /* FIXME : I'm not checking for != GST_ACTIVATE_correct_direction
+ * because the pad might not be activated yet.
+ * This means that _add_probe() might return a valid probeid ...
+ * which will potentially never be called if the pad
+ * is activated in the wrong direction */
+ if (G_UNLIKELY ((mask & GST_PROBE_TYPE_PUSH) &&
+ (GST_PAD_ACTIVATE_MODE (pad) == GST_ACTIVATE_PULL)))
+ goto wrong_direction;
+ if (G_UNLIKELY ((mask & GST_PROBE_TYPE_PULL) &&
+ (GST_PAD_ACTIVATE_MODE (pad) == GST_ACTIVATE_PUSH)))
+ goto wrong_direction;
+
/* make a new probe */
hook = g_hook_alloc (&pad->probes);
@@ -1127,6 +1140,15 @@ gst_pad_add_probe (GstPad * pad, GstProbeType mask,
GST_OBJECT_UNLOCK (pad);
}
return res;
+
+wrong_direction:
+ {
+ GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pad block on the wrong pad, "
+ "block src pads in push mode and sink pads in pull mode.");
+ GST_OBJECT_UNLOCK (pad);
+
+ return 0;
+ }
}
static void
@@ -4221,10 +4243,11 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
/* Remove sticky EOS events */
GST_LOG_OBJECT (pad, "Removing pending EOS events");
- gst_event_replace (&pad->priv->
- events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].pending, NULL);
- gst_event_replace (&pad->priv->
- events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].event, NULL);
+ gst_event_replace (&pad->
+ priv->events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].pending,
+ NULL);
+ gst_event_replace (&pad->
+ priv->events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].event, NULL);
if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-stop");
@@ -4432,10 +4455,11 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
}
/* Remove pending EOS events */
GST_LOG_OBJECT (pad, "Removing pending EOS events");
- gst_event_replace (&pad->priv->
- events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].pending, NULL);
- gst_event_replace (&pad->priv->
- events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].event, NULL);
+ gst_event_replace (&pad->
+ priv->events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].pending,
+ NULL);
+ gst_event_replace (&pad->
+ priv->events[GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_EOS)].event, NULL);
GST_OBJECT_UNLOCK (pad);
/* grab stream lock */
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index 90407eae2..b9527e976 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -2,6 +2,8 @@
* Copyright (C) 2008 Nokia Corporation. All rights reserved.
* Contact: Stefan Kost <stefan.kost@nokia.com>
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -315,6 +317,12 @@ struct _GstBaseParsePrivate
/* push mode helper frame */
GstBaseParseFrame frame;
+
+ /* TRUE if we're still detecting the format, i.e.
+ * if ::detect() is still called for future buffers */
+ gboolean detecting;
+ GList *detect_buffers;
+ guint detect_buffers_size;
};
typedef struct _GstBaseParseSeek
@@ -378,6 +386,7 @@ static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query);
+static GstCaps *gst_base_parse_sink_getcaps (GstPad * pad, GstCaps * filter);
static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad);
static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
@@ -422,6 +431,11 @@ gst_base_parse_clear_queues (GstBaseParse * parse)
g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL);
g_slist_free (parse->priv->buffers_send);
parse->priv->buffers_send = NULL;
+
+ g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
+ g_list_free (parse->priv->detect_buffers);
+ parse->priv->detect_buffers = NULL;
+ parse->priv->detect_buffers_size = 0;
}
static void
@@ -509,6 +523,8 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
gst_pad_set_event_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
+ gst_pad_set_getcaps_function (parse->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_base_parse_sink_getcaps));
gst_pad_set_chain_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_chain));
gst_pad_set_activate_function (parse->sinkpad,
@@ -735,6 +751,11 @@ gst_base_parse_reset (GstBaseParse * parse)
parse->priv->frame._private_flags |=
GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
gst_base_parse_frame_free (&parse->priv->frame);
+
+ g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
+ g_list_free (parse->priv->detect_buffers);
+ parse->priv->detect_buffers = NULL;
+ parse->priv->detect_buffers_size = 0;
GST_OBJECT_UNLOCK (parse);
}
@@ -1739,7 +1760,6 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) {
gst_base_parse_push_frame (parse, queued_frame);
- gst_base_parse_frame_free (queued_frame);
}
}
@@ -2204,6 +2224,82 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_PARSE_GET_CLASS (parse);
+
+ if (parse->priv->detecting) {
+ GstBuffer *detect_buf;
+
+ if (parse->priv->detect_buffers_size == 0) {
+ detect_buf = gst_buffer_ref (buffer);
+ } else {
+ GList *l;
+ guint offset = 0;
+
+ detect_buf = gst_buffer_new ();
+
+ for (l = parse->priv->detect_buffers; l; l = l->next) {
+ gsize tmpsize = gst_buffer_get_size (l->data);
+
+ gst_buffer_copy_into (detect_buf, GST_BUFFER_CAST (l->data),
+ GST_BUFFER_COPY_MEMORY, offset, tmpsize);
+ offset += tmpsize;
+ }
+ if (buffer)
+ gst_buffer_copy_into (detect_buf, buffer, GST_BUFFER_COPY_MEMORY,
+ offset, gst_buffer_get_size (buffer));
+ }
+
+ ret = bclass->detect (parse, detect_buf);
+ gst_buffer_unref (detect_buf);
+
+ if (ret == GST_FLOW_OK) {
+ GList *l;
+
+ /* Detected something */
+ parse->priv->detecting = FALSE;
+
+ for (l = parse->priv->detect_buffers; l; l = l->next) {
+ if (ret == GST_FLOW_OK && !parse->priv->flushing)
+ ret =
+ gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
+ GST_BUFFER_CAST (l->data));
+ else
+ gst_buffer_unref (GST_BUFFER_CAST (l->data));
+ }
+ g_list_free (parse->priv->detect_buffers);
+ parse->priv->detect_buffers = NULL;
+ parse->priv->detect_buffers_size = 0;
+
+ if (ret != GST_FLOW_OK) {
+ return ret;
+ }
+
+ /* Handle the current buffer */
+ } else if (ret == GST_FLOW_NOT_NEGOTIATED) {
+ /* Still detecting, append buffer or error out if draining */
+
+ if (parse->priv->drain) {
+ GST_DEBUG_OBJECT (parse, "Draining but did not detect format yet");
+ return GST_FLOW_ERROR;
+ } else if (parse->priv->flushing) {
+ g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref,
+ NULL);
+ g_list_free (parse->priv->detect_buffers);
+ parse->priv->detect_buffers = NULL;
+ parse->priv->detect_buffers_size = 0;
+ } else {
+ parse->priv->detect_buffers =
+ g_list_append (parse->priv->detect_buffers, buffer);
+ parse->priv->detect_buffers_size += gst_buffer_get_size (buffer);
+ return GST_FLOW_OK;
+ }
+ } else {
+ /* Something went wrong, subclass responsible for error reporting */
+ return ret;
+ }
+
+ /* And now handle the current buffer if detection worked */
+ }
+
frame = &parse->priv->frame;
if (G_LIKELY (buffer)) {
@@ -2584,6 +2680,30 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
if (gst_buffer_get_size (buffer) < min_size)
parse->priv->drain = TRUE;
+ if (parse->priv->detecting) {
+ ret = klass->detect (parse, buffer);
+ if (ret == GST_FLOW_NOT_NEGOTIATED) {
+ /* If draining we error out, otherwise request a buffer
+ * with 64kb more */
+ if (parse->priv->drain) {
+ gst_buffer_unref (buffer);
+ GST_ERROR_OBJECT (parse, "Failed to detect format but draining");
+ return GST_FLOW_ERROR;
+ } else {
+ fsize += 64 * 1024;
+ gst_buffer_unref (buffer);
+ continue;
+ }
+ } else if (ret != GST_FLOW_OK) {
+ gst_buffer_unref (buffer);
+ GST_ERROR_OBJECT (parse, "detect() returned %s",
+ gst_flow_get_name (ret));
+ return ret;
+ }
+
+ /* Else handle this buffer normally */
+ }
+
skip = -1;
gst_base_parse_frame_update (parse, frame, buffer);
res = klass->check_valid_frame (parse, frame, &fsize, &skip);
@@ -2821,6 +2941,10 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active)
if (active) {
if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start)
result = klass->start (parse);
+
+ /* If the subclass implements ::detect we want to
+ * call it for the first buffers now */
+ parse->priv->detecting = (klass->detect != NULL);
} else {
/* We must make sure streaming has finished before resetting things
* and calling the ::stop vfunc */
@@ -3842,6 +3966,29 @@ gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event)
}
}
+static GstCaps *
+gst_base_parse_sink_getcaps (GstPad * pad, GstCaps * filter)
+{
+ GstBaseParse *parse;
+ GstBaseParseClass *klass;
+ GstCaps *caps;
+
+ parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+ klass = GST_BASE_PARSE_GET_CLASS (parse);
+ g_assert (pad == GST_BASE_PARSE_SINK_PAD (parse));
+
+ if (klass->get_sink_caps)
+ caps = klass->get_sink_caps (parse, filter);
+ else
+ caps = gst_pad_proxy_getcaps (pad, filter);
+ gst_object_unref (parse);
+
+ GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT, caps);
+
+ return caps;
+
+}
+
static void
gst_base_parse_set_index (GstElement * element, GstIndex * index)
{
diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h
index 655ad0e4a..72946a614 100644
--- a/libs/gst/base/gstbaseparse.h
+++ b/libs/gst/base/gstbaseparse.h
@@ -191,6 +191,7 @@ struct _GstBaseParse {
* Called when the element stops processing.
* Allows closing external resources.
* @set_sink_caps: allows the subclass to be notified of the actual caps set.
+ * @get_sink_caps: allows the subclass to do its own sink get caps if needed.
* @check_valid_frame: Check if the given piece of data contains a valid
* frame.
* @parse_frame: Parse the already checked frame. Subclass need to
@@ -211,6 +212,10 @@ struct _GstBaseParse {
* additional actions at this time (e.g. tag sending) or to
* decide whether this buffer should be dropped or not
* (e.g. custom segment clipping).
+ * @detect: Optional.
+ * Called until it doesn't return GST_FLOW_OK anymore for
+ * the first buffers. Can be used by the subclass to detect
+ * the stream format. Since: 0.10.36
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @check_valid_frame and @parse_frame needs to be
@@ -252,8 +257,14 @@ struct _GstBaseParseClass {
gboolean (*src_event) (GstBaseParse * parse,
GstEvent * event);
+ GstCaps * (*get_sink_caps) (GstBaseParse * parse,
+ GstCaps * filter);
+
+ GstFlowReturn (*detect) (GstBaseParse * parse,
+ GstBuffer * buffer);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ gpointer _gst_reserved[GST_PADDING_LARGE - 2];
};
GType gst_base_parse_get_type (void);
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 1e5445a1e..75dabf90b 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -2057,8 +2057,8 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
/* FIXME: Casting to GstClockEntry only works because the types
* are the same */
if (G_LIKELY (sink->priv->cached_clock_id != NULL
- && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->
- priv->cached_clock_id) == clock)) {
+ && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->priv->
+ cached_clock_id) == clock)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) {
gst_clock_id_unref (sink->priv->cached_clock_id);
@@ -4431,6 +4431,10 @@ gst_base_sink_send_event (GstElement * element, GstEvent * event)
}
gst_object_unref (pad);
+
+ GST_DEBUG_OBJECT (basesink, "handled event %p %" GST_PTR_FORMAT ": %d", event,
+ event, result);
+
return result;
}