[rhythmbox] metadata: ignore non-media files better



commit bdf8dfaef826256d0419d3098a30e5e54232e27e
Author: Jonathan Matthew <jonathan d14n org>
Date:   Thu Mar 1 09:03:36 2012 +1000

    metadata: ignore non-media files better
    
    When GstDiscoverer doesn't give us any stream information, run
    a simple typefinding pipeline to get the media type.  Its result
    isn't always GST_DISCOVERER_MISSING_PLUGINS when there is missing
    plugin information, so don't rely on it.

 lib/rb-gst-media-types.c            |    5 ++
 metadata/rb-metadata-dbus-service.c |    1 +
 metadata/rb-metadata-gst.c          |  117 +++++++++++++++++++++++++++-------
 3 files changed, 99 insertions(+), 24 deletions(-)
---
diff --git a/lib/rb-gst-media-types.c b/lib/rb-gst-media-types.c
index 65ea345..c691a18 100644
--- a/lib/rb-gst-media-types.c
+++ b/lib/rb-gst-media-types.c
@@ -60,6 +60,11 @@ rb_gst_get_missing_plugin_type (const GstStructure *structure)
 	const GValue *val;
 	int i;
 
+	if (structure == NULL) {
+		rb_debug ("no missing plugin details");
+		return MEDIA_TYPE_NONE;
+	}
+
 	missing_type = gst_structure_get_string (structure, "type");
 	if (missing_type == NULL || strcmp (missing_type, "decoder") != 0) {
 		rb_debug ("missing plugin is not a decoder");
diff --git a/metadata/rb-metadata-dbus-service.c b/metadata/rb-metadata-dbus-service.c
index 084a43a..cb29d33 100644
--- a/metadata/rb-metadata-dbus-service.c
+++ b/metadata/rb-metadata-dbus-service.c
@@ -284,6 +284,7 @@ test_load (const char *uri)
 	if (error) {
 		g_print ("Error loading metadata from %s: %s\n", uri, error->message);
 		g_clear_error (&error);
+		g_print ("media type: %s\n", rb_metadata_get_media_type (md));
 		rv = -1;
 	} else {
 		int i;
diff --git a/metadata/rb-metadata-gst.c b/metadata/rb-metadata-gst.c
index cdfcae2..52548da 100644
--- a/metadata/rb-metadata-gst.c
+++ b/metadata/rb-metadata-gst.c
@@ -90,6 +90,72 @@ rb_metadata_reset (RBMetaData *md)
 	md->priv->has_video = FALSE;
 }
 
+static void
+have_type_cb (GstElement *element, guint probability, GstCaps *caps, RBMetaData *md)
+{
+	md->priv->mediatype = rb_gst_caps_to_media_type (caps);
+	rb_debug ("got type %s", md->priv->mediatype);
+}
+
+static void
+run_typefind (RBMetaData *md, const char *uri)
+{
+	GstElement *src;
+
+	src = gst_element_make_from_uri (GST_URI_SRC, uri, NULL);
+	if (src != NULL) {
+		GstElement *pipeline = gst_pipeline_new (NULL);
+		GstElement *sink = gst_element_factory_make ("fakesink", NULL);
+		GstElement *typefind = gst_element_factory_make ("typefind", NULL);
+
+		gst_bin_add_many (GST_BIN (pipeline), src, typefind, sink, NULL);
+		if (gst_element_link_many (src, typefind, sink, NULL)) {
+			GstBus *bus;
+			GstMessage *message;
+			gboolean done;
+
+			g_signal_connect (typefind, "have-type", G_CALLBACK (have_type_cb), md);
+
+			bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+			gst_element_set_state (pipeline, GST_STATE_PAUSED);
+			done = FALSE;
+
+			while (done == FALSE && md->priv->mediatype == NULL) {
+				message = gst_bus_timed_pop (bus, 5 * GST_SECOND);
+				if (message == NULL) {
+					rb_debug ("typefind pass timed out");
+					break;
+				}
+
+				switch (GST_MESSAGE_TYPE (message)) {
+				case GST_MESSAGE_ERROR:
+					rb_debug ("typefind pass got an error");
+					done = TRUE;
+					break;
+
+				case GST_MESSAGE_STATE_CHANGED:
+					if (GST_MESSAGE_SRC (message) == GST_OBJECT (pipeline)) {
+						GstState old, new, pending;
+						gst_message_parse_state_changed (message, &old, &new, &pending);
+						if (new == GST_STATE_PAUSED && pending == GST_STATE_VOID_PENDING) {
+							rb_debug ("typefind pipeline reached PAUSED");
+							done = TRUE;
+						}
+					}
+					break;
+
+				default:
+					break;
+				}
+			}
+
+			gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+		}
+
+		g_object_unref (pipeline);
+	}
+}
+
 void
 rb_metadata_load (RBMetaData *md, const char *uri, GError **error)
 {
@@ -153,41 +219,44 @@ rb_metadata_load (RBMetaData *md, const char *uri, GError **error)
 	}
 	gst_discoverer_stream_info_list_free (streams);
 
+	/* if we don't have a media type, use typefind to get one */
+	if (md->priv->mediatype == NULL) {
+		run_typefind (md, uri);
+	}
+
 	/* look at missing plugin information too */
-	if (rb_metadata_has_missing_plugins (md)) {
-		switch (rb_gst_get_missing_plugin_type (gst_discoverer_info_get_misc (md->priv->info))) {
-		case MEDIA_TYPE_NONE:
-			break;
-		case MEDIA_TYPE_CONTAINER:
-			/* hm, maybe we need a way to say 'we don't even know what's in here'.
-			 * but for now, the things we actually identify as containers are mostly
-			 * used for audio, so pretending they actually are is good enough.
-			 */
-		case MEDIA_TYPE_AUDIO:
-			md->priv->has_audio = TRUE;
-			break;
-		case MEDIA_TYPE_VIDEO:
-			md->priv->has_video = TRUE;
-			break;
-		case MEDIA_TYPE_OTHER:
-			md->priv->has_non_audio = TRUE;
-			break;
-		default:
-			g_assert_not_reached ();
-		}
+	switch (rb_gst_get_missing_plugin_type (gst_discoverer_info_get_misc (md->priv->info))) {
+	case MEDIA_TYPE_NONE:
+		break;
+	case MEDIA_TYPE_CONTAINER:
+		/* hm, maybe we need a way to say 'we don't even know what's in here'.
+		 * but for now, the things we actually identify as containers are mostly
+		 * used for audio, so pretending they actually are is good enough.
+		 */
+	case MEDIA_TYPE_AUDIO:
+		md->priv->has_audio = TRUE;
+		break;
+	case MEDIA_TYPE_VIDEO:
+		md->priv->has_video = TRUE;
+		break;
+	case MEDIA_TYPE_OTHER:
+		md->priv->has_non_audio = TRUE;
+		break;
+	default:
+		g_assert_not_reached ();
 	}
 }
 
 gboolean
 rb_metadata_has_missing_plugins (RBMetaData *md)
 {
-	GstDiscovererResult result;
+	const GstStructure *s;
 	if (md->priv->info == NULL) {
 		return FALSE;
 	}
 
-	result = gst_discoverer_info_get_result (md->priv->info);
-	return ((result & GST_DISCOVERER_MISSING_PLUGINS) != 0);
+	s = gst_discoverer_info_get_misc (md->priv->info);
+	return (rb_gst_get_missing_plugin_type (s) != MEDIA_TYPE_NONE);
 }
 
 gboolean



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]