[rhythmbox] metadata: figure out media types for missing plugins



commit 2347fff837af53798868ee0f9dcab7ad3a7f2b5e
Author: Jonathan Matthew <jonathan d14n org>
Date:   Mon Jun 8 19:56:59 2009 +1000

    metadata: figure out media types for missing plugins
    
    We can reliably guess what media type the missing decoder or demuxer
    processes based on the GStreamer media type strings, so we use that
    information to update our knowledge of the media types in the file.
    
    We don't need to use the 'unknown-type' signal any more, since the
    missing plugin messages convey the same information more usefully.
    
    With this, we only run the codec installer for audio-only files
    (bug #537113).
---
 metadata/rb-metadata-gst-common.c |   55 +++++++++++++++++++++++++++++++++++++
 metadata/rb-metadata-gst-common.h |   10 +++++++
 metadata/rb-metadata-gst.c        |   53 ++++++++++++++++++++---------------
 3 files changed, 95 insertions(+), 23 deletions(-)

diff --git a/metadata/rb-metadata-gst-common.c b/metadata/rb-metadata-gst-common.c
index f092269..f021766 100644
--- a/metadata/rb-metadata-gst-common.c
+++ b/metadata/rb-metadata-gst-common.c
@@ -203,3 +203,58 @@ rb_metadata_gst_field_to_gst_tag (RBMetaDataField field)
 	}
 }
 
+
+/* don't like this much, but it's all we can do for now.
+ * these media types are copied from gst-plugins-base/gst-libs/gst/pbutils/descriptions.c.
+ * these are only the media types that don't start with 'audio/' or 'video/', which are
+ * identified fairly accurately by the filters for those prefixes.
+ */
+static const char *container_formats[] = {
+	"application/ogg",
+	"application/vnd.rn-realmedia",
+	"application/x-id3",
+	"application/x-ape",
+	"application/x-icy"
+};
+
+
+RBGstMediaType
+rb_metadata_gst_get_missing_plugin_type (GstMessage *message)
+{
+	const char *media_type;
+	const char *missing_type;
+	const GstStructure *structure;
+	const GstCaps *caps;
+	const GValue *val;
+	int i;
+
+	structure = gst_message_get_structure (message);
+	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");
+		return MEDIA_TYPE_NONE;
+	}
+
+	val = gst_structure_get_value (structure, "detail");
+	caps = gst_value_get_caps (val);
+
+	media_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+	for (i = 0; i < G_N_ELEMENTS (container_formats); i++) {
+		if (strcmp (media_type, container_formats[i]) == 0) {
+			rb_debug ("missing plugin is a container demuxer");
+			return MEDIA_TYPE_CONTAINER;
+		}
+	}
+
+	if (g_str_has_prefix (media_type, "audio/")) {
+		rb_debug ("missing plugin is an audio decoder");
+		return MEDIA_TYPE_AUDIO;
+	} else if (g_str_has_prefix (media_type, "video/")) {
+		rb_debug ("missing plugin is (probably) a video decoder");
+		return MEDIA_TYPE_VIDEO;
+	} else {
+		rb_debug ("missing plugin is neither a video nor audio decoder");
+		return MEDIA_TYPE_OTHER;
+	}
+}
+
diff --git a/metadata/rb-metadata-gst-common.h b/metadata/rb-metadata-gst-common.h
index 33c6592..c8b891d 100644
--- a/metadata/rb-metadata-gst-common.h
+++ b/metadata/rb-metadata-gst-common.h
@@ -34,11 +34,21 @@ G_BEGIN_DECLS
 
 #include "rb-metadata.h"
 
+typedef enum {
+	MEDIA_TYPE_NONE = 0,
+	MEDIA_TYPE_CONTAINER,
+	MEDIA_TYPE_AUDIO,
+	MEDIA_TYPE_VIDEO,
+	MEDIA_TYPE_OTHER
+} RBGstMediaType;
+
 const char *		rb_metadata_gst_field_to_gst_tag (RBMetaDataField field);
 RBMetaDataField		rb_metadata_gst_tag_to_field (const char *tag);
 
 void			rb_metadata_gst_register_transforms (void);
 
+RBGstMediaType		rb_metadata_gst_get_missing_plugin_type (GstMessage *msg);
+
 G_END_DECLS
 
 #endif /* RB_METADATA_GST_COMMON_H */
diff --git a/metadata/rb-metadata-gst.c b/metadata/rb-metadata-gst.c
index bfadd5b..b13fdb3 100644
--- a/metadata/rb-metadata-gst.c
+++ b/metadata/rb-metadata-gst.c
@@ -594,27 +594,6 @@ rb_metadata_gst_new_decoded_pad_cb (GstElement *decodebin, GstPad *pad, gboolean
 		gst_element_set_state (md->priv->pipeline, GST_STATE_NULL);
 }
 
-static void
-rb_metadata_gst_unknown_type_cb (GstElement *decodebin, GstPad *pad, GstCaps *caps, RBMetaData *md)
-{
-	if (!gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
-		GstStructure *structure;
-		const gchar *mimetype;
-
-		structure = gst_caps_get_structure (caps, 0);
-		mimetype = gst_structure_get_name (structure);
-
-		g_free (md->priv->type);
-		md->priv->type = g_strdup (mimetype);
-
-		rb_debug ("decodebin emitted unknown type signal for %s", mimetype);
-	} else {
-		rb_debug ("decodebin emitted unknown type signal");
-	}
-
-	md->priv->has_non_audio = TRUE;
-}
-
 static GstElement *make_pipeline_element (GstElement *pipeline, const char *element, GError **error)
 {
 	GstElement *elem = gst_element_factory_make (element, element);
@@ -634,10 +613,39 @@ static GstElement *make_pipeline_element (GstElement *pipeline, const char *elem
 static void
 rb_metadata_handle_missing_plugin_message (RBMetaData *md, GstMessage *message)
 {
+	char *detail;
+
+	detail = gst_missing_plugin_message_get_installer_detail (message);
 	rb_debug ("got missing-plugin message from %s: %s",
 		  GST_OBJECT_NAME (GST_MESSAGE_SRC (message)),
-		  gst_missing_plugin_message_get_installer_detail (message));
+		  detail);
+	g_free (detail);
+
 	md->priv->missing_plugins = g_slist_prepend (md->priv->missing_plugins, gst_message_ref (message));
+
+	/* update our information on what's in the stream based on
+	 * what we're missing.
+	 */
+	switch (rb_metadata_gst_get_missing_plugin_type (message)) {
+	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 ();
+	}
 }
 
 static gboolean
@@ -825,7 +833,6 @@ rb_metadata_load (RBMetaData *md,
  	}
 
  	g_signal_connect_object (decodebin, "new-decoded-pad", G_CALLBACK (rb_metadata_gst_new_decoded_pad_cb), md, 0);
- 	g_signal_connect_object (decodebin, "unknown-type", G_CALLBACK (rb_metadata_gst_unknown_type_cb), md, 0);
 
  	/* locate the decodebin's typefind, so we can get the have_type signal too.
  	 * this is kind of nasty, since it relies on an essentially arbitrary string



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