*/
/**
* SECTION:element-typefind
+ * @title: typefind
*
* Determines the media-type of a stream. It applies typefind functions in the
* order of their rank. Once the type has been detected it sets its src pad caps
GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
caps, probability);
+ /* Do nothing if downstream is pulling from us */
+ if (GST_PAD_MODE (typefind->src) == GST_PAD_MODE_PULL)
+ return;
+
GST_OBJECT_LOCK (typefind);
/* Now actually send the CAPS event downstream.
GstCaps *event_caps;
gst_event_parse_caps (event, &event_caps);
- if (caps == event_caps) {
- event = event;
- } else {
+ if (caps != event_caps) {
gst_event_unref (event);
event = gst_event_new_caps (caps);
}
event = gst_event_new_caps (caps);
}
- if (typefind->caps)
- gst_caps_unref (typefind->caps);
- typefind->caps = gst_caps_ref (caps);
GST_OBJECT_UNLOCK (typefind);
gst_pad_push_event (typefind->src, event);
{
GstEvent *event;
+ /* Update caps field immediately so that caps queries and properties can be
+ * honored in all "have-type" signal handlers.
+ */
+ GST_OBJECT_LOCK (typefind);
+ if (typefind->caps)
+ gst_caps_unref (typefind->caps);
+ typefind->caps = gst_caps_ref (caps);
+ GST_OBJECT_UNLOCK (typefind);
+
/* Only store the caps event at this point. We give signal handlers
* the chance to look at the caps before they are sent downstream.
* They are only forwarded downstream later in the default signal
switch (format) {
case GST_FORMAT_BYTES:
peer_pos -= gst_adapter_available (typefind->adapter);
+ if (peer_pos < 0) /* Clamp result to 0 */
+ peer_pos = 0;
break;
default:
/* FIXME */
if (typefind->mode != MODE_NORMAL) {
/* need to do more? */
+ GST_LOG_OBJECT (typefind, "Still typefinding. Not passing event upstream");
gst_event_unref (event);
return FALSE;
}
if (gst_caps_is_any (caps))
return TRUE;
+ /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */
+ typefind->mode = MODE_NORMAL;
gst_type_find_element_emit_have_type (typefind, GST_TYPE_FIND_MAXIMUM, caps);
/* Shortcircuit typefinding if we get caps */
gsize avail;
const guint8 *data;
gboolean have_min, have_max;
+ gchar *ext;
GST_OBJECT_LOCK (typefind);
if (typefind->force_caps) {
if (!have_min)
goto not_enough_data;
+ ext = gst_type_find_get_extension (typefind, typefind->sink);
/* map all available data */
data = gst_adapter_map (typefind->adapter, avail);
- caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
- data, avail, &probability);
+ caps = gst_type_find_helper_for_data_with_extension (GST_OBJECT (typefind),
+ data, avail, ext, &probability);
gst_adapter_unmap (typefind->adapter);
+ g_free (ext);
if (caps == NULL && have_max)
goto no_type_found;
GST_OBJECT_UNLOCK (typefind);
- /* probability is good enough too, so let's make it known ... emiting this
+ /* probability is good enough too, so let's make it known ... emitting this
* signal calls our object handler which sets the caps. */
+ /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */
+ typefind->mode = MODE_NORMAL;
gst_type_find_element_emit_have_type (typefind, probability, caps);
/* .. and send out the accumulated data */
}
ext = gst_type_find_get_extension (typefind, pad);
- found_caps =
- gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
+ ret =
+ gst_type_find_helper_get_range_full (GST_OBJECT_CAST (peer),
GST_OBJECT_PARENT (peer),
(GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
- (guint64) size, ext, &probability);
+ (guint64) size, ext, &found_caps, &probability);
g_free (ext);
GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);
gst_object_unref (peer);
+
+ if (ret != GST_FLOW_OK)
+ goto pause;
}
}
goto pause;
}
- GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
- gst_type_find_element_emit_have_type (typefind, probability, found_caps);
+ GST_DEBUG ("Emitting found caps %" GST_PTR_FORMAT, found_caps);
+ /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */
typefind->mode = MODE_NORMAL;
+ gst_type_find_element_emit_have_type (typefind, probability, found_caps);
gst_caps_unref (found_caps);
} else if (typefind->mode == MODE_NORMAL) {
GstBuffer *outbuf = NULL;
}
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
/* for fatal errors we post an error message */
- GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL),
- ("stream stopped, reason %s", reason));
+ GST_ELEMENT_FLOW_ERROR (typefind, ret);
push_eos = TRUE;
}
if (push_eos) {
{
GstQuery *query;
gboolean pull_mode;
- GstSchedulingFlags sched_flags;
query = gst_query_new_scheduling ();
goto typefind_push;
}
- gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
-
- pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL)
- && ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0);
+ pull_mode = gst_query_has_scheduling_mode_with_flags (query,
+ GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
gst_query_unref (query);