*/
/**
* 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
/* Require at least 2kB of data before we attempt typefinding in chain-mode.
* 128kB is massive overkill for the maximum, but doesn't do any harm */
+#ifdef TIZEN_PROFILE_TV
+/* TV demuxer needs 4*1024 as min size to match demuxer, if not
+ * sometimes can't find correct demuxer
+ */
+#define TYPE_FIND_MIN_SIZE (4*1024)
+#else
#define TYPE_FIND_MIN_SIZE (2*1024)
+#endif
#define TYPE_FIND_MAX_SIZE (128*1024)
/* TypeFind signals and args */
gst_type_find_element_have_type (GstTypeFindElement * typefind,
guint probability, GstCaps * caps)
{
+ GstEvent *event;
+
g_assert (caps != NULL);
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.
+ *
+ * Try to directly send the CAPS event downstream that we created in
+ * gst_type_find_element_emit_have_type() if it is still there, instead
+ * of creating a new one. No need to create an equivalent one, replacing
+ * it in the sticky event list and possibly causing renegotiation
+ */
+ event = gst_pad_get_sticky_event (typefind->src, GST_EVENT_CAPS, 0);
+ if (event) {
+ GstCaps *event_caps;
+
+ gst_event_parse_caps (event, &event_caps);
+ if (caps != event_caps) {
+ gst_event_unref (event);
+ event = gst_event_new_caps (caps);
+ }
+ } else {
+ event = gst_event_new_caps (caps);
+ }
+
+ GST_OBJECT_UNLOCK (typefind);
+
+ gst_pad_push_event (typefind->src, event);
+}
+
+static void
+gst_type_find_element_emit_have_type (GstTypeFindElement * typefind,
+ guint probability, GstCaps * caps)
+{
+ GstEvent *event;
+
+ /* Update caps field immediatly 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);
- gst_pad_set_caps (typefind->src, caps);
+ /* 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
+ * handler after all application signal handlers
+ */
+ event = gst_event_new_caps (caps);
+ gst_pad_store_sticky_event (typefind->src, event);
+ gst_event_unref (event);
+
+ g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
+ probability, caps);
}
static void
"Generic",
"Finds the media type of a stream",
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&type_find_element_src_template));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&type_find_element_sink_template));
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &type_find_element_src_template);
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &type_find_element_sink_template);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
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;
- g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
- GST_TYPE_FIND_MAXIMUM, 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, GST_TYPE_FIND_MAXIMUM, caps);
/* Shortcircuit typefinding if we get caps */
GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
/* probability is good enough too, so let's make it known ... emiting this
* signal calls our object handler which sets the caps. */
- g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
- probability, 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 */
stop_typefinding (typefind);
if (at_eos) {
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
- (_("Stream contains not enough data.")), ("Can't typefind stream"));
+ (_("Stream doesn't contain enough data.")),
+ ("Can't typefind stream"));
return GST_FLOW_ERROR;
} else {
GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
if (at_eos) {
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
- (_("Stream contains not enough data.")), ("Can't typefind stream"));
+ (_("Stream doesn't contain enough data.")),
+ ("Can't typefind stream"));
return GST_FLOW_ERROR;
} else {
GST_DEBUG_OBJECT (typefind,
}
GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
- g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
- 0, probability, 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);