tracker r2854 - in trunk: . src/tracker-extract
- From: mottela svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r2854 - in trunk: . src/tracker-extract
- Date: Wed, 28 Jan 2009 12:49:39 +0000 (UTC)
Author: mottela
Date: Wed Jan 28 12:49:39 2009
New Revision: 2854
URL: http://svn.gnome.org/viewvc/tracker?rev=2854&view=rev
Log:
Added an initial tagreadbin extractor
Added:
trunk/src/tracker-extract/tracker-extract-gstreamer-tagreadbin.c
Modified:
trunk/ChangeLog
Added: trunk/src/tracker-extract/tracker-extract-gstreamer-tagreadbin.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-extract/tracker-extract-gstreamer-tagreadbin.c Wed Jan 28 12:49:39 2009
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* This extractor is still unfinished as required support from
+ * tagreadbin for streaminfo elements is missing
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/tag/tag.h>
+#include <gst/interfaces/tagreader.h>
+
+#include "tracker-extract.h"
+#include "tracker-albumart.h"
+
+typedef enum {
+ EXTRACT_MIME_UNDEFINED,
+ EXTRACT_MIME_AUDIO,
+ EXTRACT_MIME_VIDEO,
+ EXTRACT_MIME_IMAGE
+} ExtractMime;
+
+typedef struct {
+ GMainLoop *loop;
+
+ GstElement *bin;
+ GstElement *filesrc;
+ GstElement *cache;
+ GstElement *pipeline;
+
+ GstBus *bus;
+ guint id;
+
+ GList *fsinks;
+
+ ExtractMime mime;
+
+ GstTagList *tagcache;
+
+} MetadataExtractor;
+
+const guint use_dbin = 0;
+const guint use_cache = 0;
+
+static void extract_gstreamer_audio (const gchar *uri, GHashTable *metadata);
+static void extract_gstreamer_video (const gchar *uri, GHashTable *metadata);
+static void extract_gstreamer_image (const gchar *uri, GHashTable *metadata);
+
+static TrackerExtractorData data[] = {
+ { "audiotag/*", extract_gstreamer_audio },
+ { "videotag/*", extract_gstreamer_video },
+ { "imagetag/*", extract_gstreamer_image },
+ { NULL, NULL }
+};
+
+static void
+add_string_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gchar *s;
+ gboolean ret;
+
+ s = NULL;
+ ret = gst_tag_list_get_string (tag_list, tag, &s);
+
+ if (s) {
+ if (ret && s[0] != '\0') {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata (s));
+ }
+
+ g_free (s);
+ }
+}
+
+static void
+add_uint_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ guint n;
+
+ ret = gst_tag_list_get_uint (tag_list, tag, &n);
+
+ if (ret) {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata_printf ("%d", n));
+ }
+}
+
+static void
+add_double_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ gdouble n;
+
+ ret = gst_tag_list_get_double (tag_list, tag, &n);
+
+ if (ret) {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata_printf ("%f", n));
+ }
+}
+
+static void
+add_y_date_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ GDate *date;
+ gboolean ret;
+
+ date = NULL;
+ ret = gst_tag_list_get_date (tag_list, tag, &date);
+
+ if (ret) {
+ gchar buf[10];
+
+ if (g_date_strftime (buf, 10, "%Y", date)) {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata (buf));
+ }
+ }
+
+ if (date) {
+ g_date_free (date);
+ }
+}
+
+static gint64
+get_media_duration (MetadataExtractor *extractor)
+{
+ gint64 duration;
+ GstFormat fmt;
+
+ g_return_val_if_fail (extractor, -1);
+ g_return_val_if_fail (extractor->bin, -1);
+
+ fmt = GST_FORMAT_TIME;
+
+ duration = -1;
+
+ if (gst_element_query_duration (extractor->bin,
+ &fmt,
+ &duration) &&
+ duration >= 0) {
+ return duration / GST_SECOND;
+ } else {
+ return -1;
+ }
+}
+
+static void
+extract_metadata (MetadataExtractor *extractor,
+ GHashTable *metadata)
+{
+ gint64 duration;
+
+ g_return_if_fail (extractor);
+ g_return_if_fail (metadata);
+
+ if (extractor->tagcache) {
+
+ /* General */
+ add_string_gst_tag (metadata, "File:Copyright", extractor->tagcache, GST_TAG_COPYRIGHT);
+ add_string_gst_tag (metadata, "File:License", extractor->tagcache, GST_TAG_LICENSE);
+ add_string_gst_tag (metadata, "DC:Coverage", extractor->tagcache, GST_TAG_LOCATION);
+
+ /* Audio */
+ add_string_gst_tag (metadata, "Audio:Album", extractor->tagcache, GST_TAG_ALBUM);
+ add_uint_gst_tag (metadata, "Audio:AlbumTrackCount", extractor->tagcache, GST_TAG_TRACK_COUNT);
+ add_uint_gst_tag (metadata, "Audio:TrackNo", extractor->tagcache, GST_TAG_TRACK_NUMBER);
+ add_uint_gst_tag (metadata, "Audio:DiscNo", extractor->tagcache, GST_TAG_ALBUM_VOLUME_NUMBER);
+ add_string_gst_tag (metadata, "Audio:Performer", extractor->tagcache, GST_TAG_PERFORMER);
+ add_double_gst_tag (metadata, "Audio:TrackGain", extractor->tagcache, GST_TAG_TRACK_GAIN);
+ add_double_gst_tag (metadata, "Audio:PeakTrackGain", extractor->tagcache, GST_TAG_TRACK_PEAK);
+ add_double_gst_tag (metadata, "Audio:AlbumGain", extractor->tagcache, GST_TAG_ALBUM_GAIN);
+ add_double_gst_tag (metadata, "Audio:AlbumPeakGain", extractor->tagcache, GST_TAG_ALBUM_PEAK);
+ add_y_date_gst_tag (metadata, "Audio:ReleaseDate", extractor->tagcache, GST_TAG_DATE);
+ add_string_gst_tag (metadata, "Audio:Genre", extractor->tagcache, GST_TAG_GENRE);
+ add_string_gst_tag (metadata, "Audio:Codec", extractor->tagcache, GST_TAG_AUDIO_CODEC);
+
+ /* Video */
+ add_string_gst_tag (metadata, "Video:Codec", extractor->tagcache, GST_TAG_VIDEO_CODEC);
+
+ if (extractor->mime == EXTRACT_MIME_IMAGE) {
+ add_string_gst_tag (metadata, "Image:Title", extractor->tagcache, GST_TAG_TITLE);
+ add_string_gst_tag (metadata, "Image:Comments", extractor->tagcache, GST_TAG_COMMENT);
+ add_string_gst_tag (metadata, "Image:Author", extractor->tagcache, GST_TAG_ARTIST);
+ } else if (extractor->mime == EXTRACT_MIME_VIDEO) {
+ add_string_gst_tag (metadata, "Video:Title", extractor->tagcache, GST_TAG_TITLE);
+ add_string_gst_tag (metadata, "Video:Comments", extractor->tagcache, GST_TAG_COMMENT);
+ add_string_gst_tag (metadata, "Video:Author", extractor->tagcache, GST_TAG_ARTIST);
+ add_string_gst_tag (metadata, "File:Copyright", extractor->tagcache, GST_TAG_COPYRIGHT);
+ } else if (extractor->mime == EXTRACT_MIME_AUDIO) {
+ add_string_gst_tag (metadata, "Audio:Title", extractor->tagcache, GST_TAG_TITLE);
+ add_string_gst_tag (metadata, "Audio:Artist", extractor->tagcache, GST_TAG_ARTIST);
+ add_string_gst_tag (metadata, "Audio:Comment", extractor->tagcache, GST_TAG_COMMENT);
+ }
+ }
+
+/* duration = get_media_duration (extractor); */
+
+/* if (extractor->mime == EXTRACT_MIME_VIDEO) { */
+/* if (duration >= 0) { */
+/* add_int64_info (metadata, g_strdup ("Video:Duration"), duration); */
+/* } */
+/* } else if (extractor->mime == EXTRACT_MIME_AUDIO) { */
+/* if (duration >= 0) { */
+/* add_int64_info (metadata, g_strdup ("Audio:Duration"), duration); */
+/* } */
+/* } */
+}
+
+static void
+unlink_fsink (void *obj, void *data)
+{
+ MetadataExtractor *extractor = (MetadataExtractor *)data;
+ GstElement *fsink = (GstElement *) obj;
+
+ gst_element_unlink (extractor->bin, fsink);
+ gst_bin_remove (GST_BIN (extractor->pipeline), fsink);
+ gst_element_set_state (fsink, GST_STATE_NULL);
+}
+
+void dbin_dpad_cb (GstElement* e, GstPad* pad, gboolean cont, gpointer data)
+{
+ MetadataExtractor *extractor = (MetadataExtractor *)data;
+ GstElement *fsink;
+ GstPad *fsinkpad;
+
+ fsink = gst_element_factory_make ("fakesink", NULL);
+
+ extractor->fsinks = g_list_append (extractor->fsinks, fsink);
+
+ gst_element_set_state (fsink, GST_STATE_PAUSED);
+
+ gst_bin_add (GST_BIN_CAST (extractor->pipeline), fsink);
+ fsinkpad = gst_element_get_static_pad (fsink, "sink");
+ gst_pad_link (pad, fsinkpad);
+ gst_object_unref (fsinkpad);
+}
+
+static void
+add_tags (GstMessage *msg, MetadataExtractor *extractor)
+{
+ GstTagList *new_tags;
+ GstTagList *result;
+
+ gst_message_parse_tag (msg, &new_tags);
+
+ result = gst_tag_list_merge (extractor->tagcache,
+ new_tags,
+ GST_TAG_MERGE_KEEP);
+
+ if (extractor->tagcache) {
+ gst_tag_list_free (extractor->tagcache);
+ }
+
+ extractor->tagcache = result;
+
+ gst_tag_list_free (new_tags);
+
+}
+
+static gboolean
+metadata_bus_async_cb (GstBus *bus, GstMessage *msg, gpointer data)
+{
+ MetadataExtractor *extractor = (MetadataExtractor *)data;
+ GError *error = NULL;
+ gboolean stop = FALSE;
+
+ switch (GST_MESSAGE_TYPE (msg)) {
+ case GST_MESSAGE_ERROR:
+ gst_message_parse_error (msg, &error, NULL);
+ printf ("ERROR: %s\n", error->message);
+ g_error_free (error);
+ stop = TRUE;
+ break;
+ case GST_MESSAGE_TAG:
+ add_tags (msg, extractor);
+ break;
+ case GST_MESSAGE_EOS:
+ stop = TRUE;
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ GstElement *sender = (GstElement *) GST_MESSAGE_SRC (msg);
+ if (use_dbin && sender == extractor->pipeline) {
+ GstState newstate;
+ gst_message_parse_state_changed (msg, NULL, &newstate, NULL);
+ if (newstate == GST_STATE_PAUSED) {
+ stop = TRUE;
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+ if (stop) {
+ gst_element_set_state (extractor->pipeline, GST_STATE_READY);
+ gst_element_get_state (extractor->pipeline, NULL, NULL, 5 * GST_SECOND);
+ g_list_foreach (extractor->fsinks, unlink_fsink, extractor);
+ g_list_free (extractor->fsinks);
+ extractor->fsinks = NULL;
+ g_main_loop_quit (extractor->loop);
+ }
+
+ return TRUE;
+}
+
+static void
+tracker_extract_gstreamer (const gchar *uri,
+ GHashTable *metadata,
+ ExtractMime type)
+{
+ MetadataExtractor *extractor;
+ gchar *mrl;
+
+ g_return_if_fail (uri);
+ g_return_if_fail (metadata);
+
+ g_type_init ();
+
+ gst_init (NULL, NULL);
+
+ extractor = g_slice_new0 (MetadataExtractor);
+ extractor->loop = NULL;
+ extractor->bin = NULL;
+ extractor->filesrc = NULL;
+ extractor->cache = NULL;
+ extractor->pipeline = NULL;
+
+ extractor->bus = NULL;
+ extractor->id = 0;
+
+ extractor->fsinks = NULL;
+
+ extractor->mime = type;
+
+ extractor->tagcache = NULL;
+
+ extractor->pipeline = gst_element_factory_make ("pipeline", NULL);
+ if (!extractor->pipeline) {
+ g_error ("Failed to create pipeline");
+ return;
+ }
+ extractor->filesrc = gst_element_factory_make ("filesrc", NULL);
+ if (!extractor->filesrc) {
+ g_error ("Failed to create filesrc");
+ return;
+ }
+ if (use_cache) {
+ extractor->cache = gst_element_factory_make ("cache", NULL);
+ if (!extractor->cache) {
+ g_error ("Failed to create cache");
+ return;
+ }
+ }
+
+ if (use_dbin) {
+ extractor->bin = gst_element_factory_make ("decodebin", "decodebin");
+ if (!extractor->bin) {
+ g_error ("Failed to create decodebin");
+ return;
+ }
+ extractor->id = g_signal_connect (G_OBJECT (extractor->bin),
+ "new-decoded-pad",
+ G_CALLBACK (dbin_dpad_cb),
+ extractor->pipeline);
+ } else {
+ extractor->bin = gst_element_factory_make ("tagreadbin", "tagreadbin");
+ if (!extractor->bin) {
+ g_error ("Failed to create tagreadbin");
+ return;
+ }
+ extractor->id = 0;
+ }
+
+ gst_bin_add (GST_BIN (extractor->pipeline), extractor->filesrc);
+ gst_bin_add (GST_BIN (extractor->pipeline), extractor->bin);
+
+ if (use_cache) {
+ gst_bin_add (GST_BIN (extractor->pipeline), extractor->cache);
+ if (! gst_element_link_many (extractor->filesrc, extractor->cache, extractor->bin, NULL)) {
+ g_error ("Can't link elements\n");
+ /* FIXME Clean up */
+ return;
+ }
+ } else {
+ if (! gst_element_link_many (extractor->filesrc, extractor->bin, NULL)) {
+ g_error ("Can't link elements\n");
+ /* FIXME Clean up */
+ return;
+ }
+ }
+
+ extractor->loop = g_main_loop_new (NULL, FALSE);
+ extractor->bus = gst_pipeline_get_bus (GST_PIPELINE (extractor->pipeline));
+ gst_bus_add_watch (extractor->bus, metadata_bus_async_cb, extractor);
+
+ mrl = g_strconcat ("file://", uri, NULL);
+ g_object_set (G_OBJECT (extractor->filesrc), "location", uri, NULL);
+
+ gst_element_set_state (extractor->pipeline, GST_STATE_PAUSED);
+ g_main_loop_run (extractor->loop);
+
+ extract_metadata (extractor, metadata);
+
+ gst_element_set_state (extractor->pipeline, GST_STATE_NULL);
+ gst_object_unref (extractor->bus);
+ gst_object_unref (GST_OBJECT (extractor->pipeline));
+ g_slice_free (MetadataExtractor, extractor);
+}
+
+
+static void
+extract_gstreamer_audio (const gchar *uri, GHashTable *metadata)
+{
+ tracker_extract_gstreamer (uri, metadata, EXTRACT_MIME_AUDIO);
+}
+
+static void
+extract_gstreamer_video (const gchar *uri, GHashTable *metadata)
+{
+ tracker_extract_gstreamer (uri, metadata, EXTRACT_MIME_VIDEO);
+}
+
+static void
+extract_gstreamer_image (const gchar *uri, GHashTable *metadata)
+{
+ tracker_extract_gstreamer (uri, metadata, EXTRACT_MIME_IMAGE);
+}
+
+TrackerExtractorData *
+tracker_get_extractor_data (void)
+{
+ return data;
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]