[gthumb/ext: 1/18] read audio/video metadata with gstreamer
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext: 1/18] read audio/video metadata with gstreamer
- Date: Fri, 6 Nov 2009 00:15:40 +0000 (UTC)
commit 4724dc5fe9e355f25f688ac2fd6e1a2d4168085c
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sun Nov 1 21:09:42 2009 +0100
read audio/video metadata with gstreamer
configure.ac | 19 +
extensions/Makefile.am | 1 +
extensions/gstreamer/Makefile.am | 34 +
extensions/gstreamer/gstreamer-utils.c | 690 ++++++++++++++++++++
extensions/gstreamer/gstreamer-utils.h | 38 ++
extensions/gstreamer/gstreamer.extension.in.in | 10 +
.../gstreamer/gth-metadata-provider-gstreamer.c | 135 ++++
.../gstreamer/gth-metadata-provider-gstreamer.h | 54 ++
extensions/gstreamer/main.c | 88 +++
extensions/image_viewer/main.c | 2 +-
gthumb/Makefile.am | 1 +
11 files changed, 1071 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1b1eaf1..4339a65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,7 @@ GCONF_REQUIRED=2.6.0
EXIV2_REQUIRED=0.18
CLUTTER_REQUIRED=1.0.0
CLUTTER_GTK_REQUIRED=0.10.0
+GSTREAMER_REQUIRED=0.10
dnl ===========================================================================
@@ -133,6 +134,22 @@ AM_CONDITIONAL(ENABLE_CLUTTER, test "x$enable_clutter" = xyes)
dnl ===========================================================================
+AC_ARG_ENABLE([gstreamer],
+ [AS_HELP_STRING([--disable-gstreamer],[do not compile code that uses the gstreamer library])],,
+ [enable_gstreamer=yes])
+
+if test x$enable_gstreamer = xyes ; then
+ PKG_CHECK_MODULES(GSTREAMER,
+ [gstreamer-0.10 >= $GSTREAMER_REQUIRED],
+ [enable_gstreamer=yes],
+ [enable_gstreamer=no])
+fi
+AC_SUBST(GSTREAMER_LIBS)
+AC_SUBST(GSTREAMER_CFLAGS)
+AM_CONDITIONAL(ENABLE_GSTREAMER, test "x$enable_gstreamer" = xyes)
+
+dnl ===========================================================================
+
IT_PROG_INTLTOOL([0.35.0])
GETTEXT_PACKAGE=gthumb
AC_SUBST([GETTEXT_PACKAGE])
@@ -295,6 +312,7 @@ extensions/file_tools/Makefile
extensions/file_tools/data/Makefile
extensions/file_tools/data/ui/Makefile
extensions/file_viewer/Makefile
+extensions/gstreamer/Makefile
extensions/image_rotation/Makefile
extensions/image_viewer/Makefile
extensions/image_viewer/data/Makefile
@@ -346,4 +364,5 @@ Configuration:
JPEG tools : ${enable_jpeg}
TIFF tools : ${enable_tiff}
Clutter support : ${enable_clutter}
+ GStreamer support : ${enable_gstreamer}
"
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 6a326f0..91bad31 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -7,6 +7,7 @@ SUBDIRS = \
file_manager \
file_tools \
file_viewer \
+ gstreamer \
image_rotation \
image_viewer \
jpeg_utils \
diff --git a/extensions/gstreamer/Makefile.am b/extensions/gstreamer/Makefile.am
new file mode 100644
index 0000000..a1b1774
--- /dev/null
+++ b/extensions/gstreamer/Makefile.am
@@ -0,0 +1,34 @@
+if ENABLE_GSTREAMER
+
+extensiondir = $(libdir)/gthumb-2.0/extensions
+extension_LTLIBRARIES = libgstreamer.la
+
+libgstreamer_la_SOURCES = \
+ gstreamer-utils.c \
+ gstreamer-utils.h \
+ gth-metadata-provider-gstreamer.c \
+ gth-metadata-provider-gstreamer.h \
+ main.c
+
+libgstreamer_la_CPPFLAGS = $(GTHUMB_CFLAGS) $(GSTREAMER_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
+libgstreamer_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
+libgstreamer_la_LIBADD = $(GTHUMB_LIBS)
+libgstreamer_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = gstreamer.extension.in.in
+extensionini_DATA = $(extensionini_in_files:.extension.in.in=.extension)
+
+%.extension.in: %.extension.in.in $(extension_LTLIBRARIES)
+ sed -e "s|%LIBRARY%|`. ./$(extension_LTLIBRARIES) && echo $$dlname`|" \
+ $< > $@
+
+%.extension: %.extension.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+EXTRA_DIST = $(extensionini_in_files)
+
+DISTCLEANFILES = $(extensionini_DATA)
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/gstreamer/gstreamer-utils.c b/extensions/gstreamer/gstreamer-utils.c
new file mode 100644
index 0000000..66c9ca5
--- /dev/null
+++ b/extensions/gstreamer/gstreamer-utils.c
@@ -0,0 +1,690 @@
+/* -*- Mode: CPP; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2008-2009 Free Software Foundation, Inc.
+ *
+ * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+/* This was based on a file from Tracker */
+/*
+ * Tracker - audio/video metadata extraction based on GStreamer
+ * Copyright (C) 2006, Laurent Aguerreche (laurent aguerreche free fr)
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <gst/gst.h>
+#include <gthumb.h>
+#include "gstreamer-utils.h"
+
+
+static gboolean gstreamer_initialized = FALSE;
+
+
+typedef struct {
+ GstElement *playbin;
+
+ GstTagList *tagcache;
+ GstTagList *audiotags;
+ GstTagList *videotags;
+ GstTagList *demuxertags;
+
+ gboolean has_audio;
+ gboolean has_video;
+
+ gint video_height;
+ gint video_width;
+ gint video_fps_n;
+ gint video_fps_d;
+ gint video_bitrate;
+ char *video_codec;
+ gint audio_channels;
+ gint audio_samplerate;
+ gint audio_bitrate;
+ char *audio_codec;
+} MetadataExtractor;
+
+
+static void
+reset_extractor_data (MetadataExtractor *extractor)
+{
+ if (extractor->tagcache != NULL) {
+ gst_tag_list_free (extractor->tagcache);
+ extractor->tagcache = NULL;
+ }
+
+ if (extractor->audiotags != NULL) {
+ gst_tag_list_free (extractor->audiotags);
+ extractor->audiotags = NULL;
+ }
+
+ if (extractor->videotags != NULL) {
+ gst_tag_list_free (extractor->videotags);
+ extractor->videotags = NULL;
+ }
+
+ if (extractor->demuxertags != NULL) {
+ gst_tag_list_free (extractor->demuxertags);
+ extractor->demuxertags = NULL;
+ }
+
+ g_free (extractor->audio_codec);
+ extractor->audio_codec = NULL;
+
+ g_free (extractor->video_codec);
+ extractor->video_codec = NULL;
+
+ extractor->has_audio = FALSE;
+ extractor->has_video = FALSE;
+ extractor->video_fps_n = -1;
+ extractor->video_fps_d = -1;
+ extractor->video_height = -1;
+ extractor->video_width = -1;
+ extractor->video_bitrate = -1;
+ extractor->audio_channels = -1;
+ extractor->audio_samplerate = -1;
+ extractor->audio_bitrate = -1;
+}
+
+
+static void
+metadata_extractor_free (MetadataExtractor *extractor)
+{
+ reset_extractor_data (extractor);
+ gst_element_set_state (extractor->playbin, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (extractor->playbin));
+ g_slice_free (MetadataExtractor, extractor);
+}
+
+
+static gboolean
+gstreamer_init (void)
+{
+ if (! gstreamer_initialized) {
+ if (! gst_init_check (NULL, NULL, NULL))
+ return FALSE;
+ gstreamer_initialized = TRUE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+add_metadata (GFileInfo *info,
+ const char *key,
+ char *raw,
+ char *formatted)
+{
+ GthMetadata *metadata;
+
+ if (raw == NULL)
+ return;
+
+ metadata = gth_metadata_new ();
+ g_object_set (metadata,
+ "id", key,
+ "formatted", formatted != NULL ? formatted : raw,
+ "raw", raw,
+ NULL);
+ g_file_info_set_attribute_object (info, key, G_OBJECT (metadata));
+
+ g_object_unref (metadata);
+ g_free (raw);
+ g_free (formatted);
+}
+
+
+static void
+add_metadata_from_tag (GFileInfo *info,
+ const GstTagList *list,
+ const char *tag,
+ const char *tag_key)
+{
+ GType tag_type;
+
+ tag_type = gst_tag_get_type (tag);
+
+ if (tag_type == G_TYPE_BOOLEAN) {
+ gboolean ret;
+ if (gst_tag_list_get_boolean (list, tag, &ret)) {
+ if (ret)
+ add_metadata (info, tag_key, g_strdup ("TRUE"), NULL);
+ else
+ add_metadata (info, tag_key, g_strdup ("FALSE"), NULL);
+ }
+ }
+
+ if (tag_type == G_TYPE_STRING) {
+ char *ret = NULL;
+ if (gst_tag_list_get_string (list, tag, &ret))
+ add_metadata (info, tag_key, ret, NULL);
+ }
+
+ if (tag_type == G_TYPE_UCHAR) {
+ guchar ret = 0;
+ if (gst_tag_list_get_uchar (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%u", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_CHAR) {
+ gchar ret = 0;
+ if (gst_tag_list_get_char (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%d", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_UINT) {
+ guint ret = 0;
+ if (gst_tag_list_get_uint (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%u", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_INT) {
+ gint ret = 0;
+ if (gst_tag_list_get_int (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%d", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_ULONG) {
+ gulong ret = 0;
+ if (gst_tag_list_get_ulong (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%lu", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_LONG) {
+ glong ret = 0;
+ if (gst_tag_list_get_long (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%ld", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_INT64) {
+ gint64 ret = 0;
+ if (gst_tag_list_get_int64 (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%" G_GINT64_FORMAT, ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_UINT64) {
+ guint64 ret = 0;
+ if (gst_tag_list_get_uint64 (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%" G_GUINT64_FORMAT, ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_DOUBLE) {
+ gdouble ret = 0;
+ if (gst_tag_list_get_double (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%f", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_FLOAT) {
+ gfloat ret = 0;
+ if (gst_tag_list_get_float (list, tag, &ret))
+ add_metadata (info, tag_key, g_strdup_printf ("%f", ret), NULL);
+ }
+
+ if (tag_type == G_TYPE_DATE) {
+ GDate *ret = NULL;
+ if (gst_tag_list_get_date (list, tag, &ret)) {
+ if (ret != NULL) {
+ char buf[128];
+ char *raw;
+ char *formatted;
+
+ g_date_strftime (buf, 10, "%F %T", ret);
+ raw = g_strdup (buf);
+
+ g_date_strftime (buf, 10, "%x %X", ret);
+ formatted = g_strdup (buf);
+ add_metadata (info, tag_key, raw, formatted);
+ }
+ g_free (ret);
+ }
+ }
+}
+
+
+static void
+tag_iterate (const GstTagList *list,
+ const char *tag,
+ GFileInfo *info)
+{
+ const char *tag_key;
+ char *attribute = NULL;
+
+ tag_key = NULL;
+
+ if (strcmp (tag, "container-format") == 0) {
+ tag_key = "audio-video::general::container-format";
+ }
+ else if (strcmp (tag, "encoder") == 0) {
+ tag_key = "audio-video::general::encoder";
+ }
+ else if (strcmp (tag, "title") == 0) {
+ tag_key = "audio-video::general::title";
+ }
+ else if (strcmp (tag, "artist") == 0) {
+ tag_key = "audio-video::general::artist";
+ }
+ else if (strcmp (tag, "album") == 0) {
+ tag_key = "audio-video::general::album";
+ }
+ else if (strcmp (tag, "audio-codec") == 0) {
+ tag_key = "audio-video::audio::codec";
+ }
+ else if (strcmp (tag, "video-codec") == 0) {
+ tag_key = "audio-video::video::codec";
+ }
+
+ if (tag_key == NULL) {
+ GthMetadataInfo *metadata_info;
+
+ attribute = g_strconcat ("audio-video::other::", tag, NULL);
+ metadata_info = gth_main_get_metadata_info (attribute);
+ if (metadata_info == NULL) {
+ GthMetadataInfo info;
+
+ info.id = attribute;
+ info.display_name = gst_tag_get_nick (tag);
+ info.category = "audio-video::other";
+ info.sort_order = 500;
+ info.flags = GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW;
+ metadata_info = gth_main_register_metadata_info (&info);
+ }
+
+ tag_key = attribute;
+ }
+
+ add_metadata_from_tag (info, list, tag, tag_key);
+
+ g_free (attribute);
+}
+
+
+static gint64
+get_media_duration (MetadataExtractor *extractor)
+{
+ GstFormat fmt;
+ gint64 duration;
+
+ g_return_val_if_fail (extractor, -1);
+ g_return_val_if_fail (extractor->playbin, -1);
+
+ fmt = GST_FORMAT_TIME;
+ duration = -1;
+ if (gst_element_query_duration (extractor->playbin, &fmt, &duration) && (duration >= 0))
+ return duration / GST_SECOND;
+ else
+ return -1;
+}
+
+
+static void
+extract_metadata (MetadataExtractor *extractor,
+ GFileInfo *info)
+{
+ gint64 duration;
+
+ if (extractor->audio_channels >= 0)
+ add_metadata (info,
+ "audio-video::audio::channels",
+ g_strdup_printf ("%d", (guint) extractor->audio_channels),
+ g_strdup (extractor->audio_channels == 2 ? _("Stereo") : _("Mono")));
+
+ if (extractor->audio_samplerate >= 0)
+ add_metadata (info,
+ "audio-video::audio::samplerate",
+ g_strdup_printf ("%d", (guint) extractor->audio_samplerate),
+ g_strdup_printf ("%d Hz", (guint) extractor->audio_samplerate));
+
+ if (extractor->audio_bitrate >= 0)
+ add_metadata (info,
+ "audio-video::audio::bitrate",
+ g_strdup_printf ("%d", (guint) extractor->audio_bitrate),
+ g_strdup_printf ("%d bps", (guint) extractor->audio_bitrate));
+
+ if (extractor->video_height >= 0)
+ add_metadata (info,
+ "audio-video::video::height",
+ g_strdup_printf ("%d", (guint) extractor->video_height),
+ NULL);
+
+ if (extractor->video_width >= 0)
+ add_metadata (info,
+ "audio-video::video::width",
+ g_strdup_printf ("%d", (guint) extractor->video_width),
+ NULL);
+
+ if ((extractor->video_height >= 0) && (extractor->video_width >= 0))
+ add_metadata (info,
+ "audio-video::video::size",
+ g_strdup_printf ("%d x %d", (guint) extractor->video_width, (guint) extractor->video_height),
+ NULL);
+
+ if ((extractor->video_fps_n >= 0) && (extractor->video_fps_d >= 0))
+ add_metadata (info,
+ "audio-video::video::framerate",
+ g_strdup_printf ("%.7g", (gdouble) extractor->video_fps_n / (gdouble) extractor->video_fps_d),
+ g_strdup_printf ("%.7g fps", (gdouble) extractor->video_fps_n / (gdouble) extractor->video_fps_d));
+
+ if (extractor->video_bitrate >= 0)
+ add_metadata (info,
+ "audio-video::video::bitrate",
+ g_strdup_printf ("%d", (guint) extractor->video_bitrate),
+ g_strdup_printf ("%d bps", (guint) extractor->video_bitrate));
+
+ duration = get_media_duration (extractor);
+ if (duration >= 0)
+ add_metadata (info,
+ "audio-video::general::duration",
+ g_strdup_printf ("%" G_GINT64_FORMAT, duration),
+ g_strdup_printf ("%" G_GINT64_FORMAT " sec", duration));
+
+ if (extractor->tagcache != NULL)
+ gst_tag_list_foreach (extractor->tagcache, (GstTagForeachFunc) tag_iterate, info);
+}
+
+
+static void
+caps_set (GstPad *pad,
+ MetadataExtractor *extractor,
+ const char *type)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+
+ if ((caps = gst_pad_get_negotiated_caps (pad)) == NULL)
+ return;
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (structure == NULL) {
+ gst_caps_unref (caps);
+ return;
+ }
+
+ if (strcmp (type, "audio") == 0) {
+ gst_structure_get_int (structure, "channels", &extractor->audio_channels);
+ gst_structure_get_int (structure, "rate", &extractor->audio_samplerate);
+ gst_structure_get_int (structure, "bitrate", &extractor->audio_bitrate);
+ }
+ else if (strcmp (type, "video") == 0) {
+ gst_structure_get_fraction (structure, "framerate", &extractor->video_fps_n, &extractor->video_fps_d);
+ gst_structure_get_int (structure, "bitrate", &extractor->video_bitrate);
+ gst_structure_get_int (structure, "width", &extractor->video_width);
+ gst_structure_get_int (structure, "height", &extractor->video_height);
+ }
+
+ gst_caps_unref (caps);
+}
+
+
+static void
+update_stream_info (MetadataExtractor *extractor)
+{
+ GList *streaminfo;
+ GstPad *audiopad;
+ GstPad *videopad;
+
+ g_return_if_fail (extractor);
+
+ streaminfo = NULL;
+ audiopad = videopad = NULL;
+
+ g_object_get (extractor->playbin, "stream-info", &streaminfo, NULL);
+ streaminfo = g_list_copy (streaminfo);
+ g_list_foreach (streaminfo, (GFunc) g_object_ref, NULL);
+
+ for (/* void */ ; streaminfo; streaminfo = streaminfo->next) {
+ GObject *info;
+ int type;
+ GParamSpec *pspec;
+ GEnumValue *val;
+
+ info = streaminfo->data;
+ if (info == NULL)
+ continue;
+
+ type = -1;
+
+ g_object_get (info, "type", &type, NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info), "type");
+ val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
+
+ if (strcmp (val->value_nick, "audio") == 0) {
+ extractor->has_audio = TRUE;
+ if (audiopad == NULL)
+ g_object_get (info, "object", &audiopad, NULL);
+ }
+ else if (strcmp (val->value_nick, "video") == 0) {
+ extractor->has_video = TRUE;
+ if (videopad == NULL)
+ g_object_get (info, "object", &videopad, NULL);
+ }
+ }
+
+ if (audiopad != NULL) {
+ GstCaps *caps;
+
+ if ((caps = gst_pad_get_negotiated_caps (audiopad)) != NULL) {
+ caps_set (audiopad, extractor, "audio");
+ gst_caps_unref (caps);
+ }
+ }
+
+ if (videopad != NULL) {
+ GstCaps *caps;
+
+ if ((caps = gst_pad_get_negotiated_caps (videopad)) != NULL) {
+ caps_set (videopad, extractor, "video");
+ gst_caps_unref (caps);
+ }
+ }
+
+ g_list_foreach (streaminfo, (GFunc) g_object_unref, NULL);
+ g_list_free (streaminfo);
+}
+
+
+static gboolean
+message_loop_to_state_change (MetadataExtractor *extractor,
+ GstState state)
+{
+ GstBus *bus;
+ GstMessageType events;
+
+ g_return_val_if_fail (extractor, FALSE);
+ g_return_val_if_fail (extractor->playbin, FALSE);
+
+ bus = gst_element_get_bus (extractor->playbin);
+
+ events = (GST_MESSAGE_TAG | GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
+
+ for (;;) {
+ GstMessage *message;
+
+ message = gst_bus_timed_pop_filtered (bus, GST_SECOND * 5, events);
+ if (message == NULL)
+ goto timed_out;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_STATE_CHANGED: {
+ GstState old_state;
+ GstState new_state;
+
+ old_state = new_state = GST_STATE_NULL;
+
+ gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
+ if (old_state == new_state)
+ break;
+
+ /* we only care about playbin (pipeline) state changes */
+ if (GST_MESSAGE_SRC (message) != GST_OBJECT (extractor->playbin))
+ break;
+
+ if ((old_state == GST_STATE_READY) && (new_state == GST_STATE_PAUSED))
+ update_stream_info (extractor);
+ else if ((old_state == GST_STATE_PAUSED) && (new_state == GST_STATE_READY))
+ reset_extractor_data (extractor);
+
+ if (new_state == state) {
+ gst_message_unref (message);
+ goto success;
+ }
+
+ break;
+ }
+
+ case GST_MESSAGE_TAG: {
+ GstTagList *tag_list;
+ GstTagList *result;
+ GstElementFactory *f;
+
+ tag_list = NULL;
+ gst_message_parse_tag (message, &tag_list);
+
+ /* all tags */
+
+ result = gst_tag_list_merge (extractor->tagcache, tag_list, GST_TAG_MERGE_KEEP);
+ if (extractor->tagcache != NULL)
+ gst_tag_list_free (extractor->tagcache);
+ extractor->tagcache = result;
+
+ /* media-type-specific tags */
+
+ if (GST_IS_ELEMENT (message->src) && (f = gst_element_get_factory (GST_ELEMENT (message->src)))) {
+ const char *klass;
+ GstTagList **cache;
+
+ klass = gst_element_factory_get_klass (f);
+
+ cache = NULL;
+ if (g_strrstr (klass, "Audio"))
+ cache = &extractor->audiotags;
+ else if (g_strrstr (klass, "Video"))
+ cache = &extractor->videotags;
+ else if (g_strrstr (klass, "Demuxer"))
+ cache = &extractor->demuxertags;
+
+ if (cache != NULL) {
+ result = gst_tag_list_merge (*cache, tag_list, GST_TAG_MERGE_KEEP);
+ if (*cache != NULL)
+ gst_tag_list_free (*cache);
+ *cache = result;
+ }
+ }
+
+ /* clean up */
+ gst_tag_list_free (tag_list);
+
+ break;
+ }
+
+ case GST_MESSAGE_ERROR: {
+ gchar *debug = NULL;
+ GError *gsterror = NULL;
+
+ gst_message_parse_error (message, &gsterror, &debug);
+
+ g_warning ("Error: %s (%s)", gsterror->message, debug);
+
+ g_error_free (gsterror);
+ gst_message_unref (message);
+ g_free (debug);
+ goto error;
+ }
+ break;
+
+ case GST_MESSAGE_EOS: {
+ g_warning ("Media file could not be played.");
+ gst_message_unref (message);
+ goto error;
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gst_message_unref (message);
+ }
+
+ g_assert_not_reached ();
+
+ success:
+ /* state change succeeded */
+ GST_DEBUG ("state change to %s succeeded", gst_element_state_get_name (state));
+ return TRUE;
+
+ timed_out:
+ /* it's taking a long time to open */
+ GST_DEBUG ("state change to %s timed out, returning success", gst_element_state_get_name (state));
+ return TRUE;
+
+ error:
+ GST_DEBUG ("error while waiting for state change to %s", gst_element_state_get_name (state));
+ /* already set *error */
+ return FALSE;
+}
+
+
+gboolean
+gstreamer_read_metadata_from_file (GFile *file,
+ GFileInfo *info,
+ GError **error)
+{
+ char *uri;
+ MetadataExtractor *extractor;
+
+ if (! gstreamer_init ())
+ return FALSE;
+
+ uri = g_file_get_uri (file);
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ extractor = g_slice_new0 (MetadataExtractor);
+ reset_extractor_data (extractor);
+
+ extractor->playbin = gst_element_factory_make ("playbin", "playbin");
+ g_object_set (G_OBJECT (extractor->playbin),
+ "uri", uri,
+ "audio-sink", gst_element_factory_make ("fakesink", "fakesink-audio"),
+ "video-sink", gst_element_factory_make ("fakesink", "fakesink-video"),
+ NULL);
+
+ gst_element_set_state (extractor->playbin, GST_STATE_PAUSED);
+ message_loop_to_state_change (extractor, GST_STATE_PAUSED);
+ extract_metadata (extractor, info);
+
+ metadata_extractor_free (extractor);
+ g_free (uri);
+
+ return TRUE;
+}
diff --git a/extensions/gstreamer/gstreamer-utils.h b/extensions/gstreamer/gstreamer-utils.h
new file mode 100644
index 0000000..d5d98b0
--- /dev/null
+++ b/extensions/gstreamer/gstreamer-utils.h
@@ -0,0 +1,38 @@
+/* -*- Mode: CPP; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GSTREAMER_UTILS_H
+#define GSTREAMER_UTILS_H
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+gboolean gstreamer_read_metadata_from_file (GFile *file,
+ GFileInfo *info,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* GSTREAMER_UTILS_H */
diff --git a/extensions/gstreamer/gstreamer.extension.in.in b/extensions/gstreamer/gstreamer.extension.in.in
new file mode 100644
index 0000000..79c375b
--- /dev/null
+++ b/extensions/gstreamer/gstreamer.extension.in.in
@@ -0,0 +1,10 @@
+[Extension]
+_Name=Audio/Video support
+_Description=Play audio and video files.
+_Authors=gthumb development team
+Copyright=Copyright © 2009 The Free Software Foundation, Inc.
+Version=1.0
+
+[Loader]
+Type=module
+File=%LIBRARY%
diff --git a/extensions/gstreamer/gth-metadata-provider-gstreamer.c b/extensions/gstreamer/gth-metadata-provider-gstreamer.c
new file mode 100644
index 0000000..f5e003d
--- /dev/null
+++ b/extensions/gstreamer/gth-metadata-provider-gstreamer.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gthumb.h>
+#include "gstreamer-utils.h"
+#include "gth-metadata-provider-gstreamer.h"
+
+
+#define GTH_METADATA_PROVIDER_GSTREAMER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_METADATA_PROVIDER_GSTREAMER, GthMetadataProviderGstreamerPrivate))
+
+
+struct _GthMetadataProviderGstreamerPrivate {
+ int dummy;
+};
+
+
+static GthMetadataProviderClass *parent_class = NULL;
+
+
+static void
+gth_metadata_provider_gstreamer_read (GthMetadataProvider *self,
+ GthFileData *file_data,
+ const char *attributes)
+{
+ if (! g_content_type_is_a (gth_file_data_get_mime_type (file_data), "audio/*")
+ && ! g_content_type_is_a (gth_file_data_get_mime_type (file_data), "video/*"))
+ {
+ return;
+ }
+
+ /* this function is executed in a secondary thread, so calling
+ * slow sync functions is not a problem. */
+
+ gstreamer_read_metadata_from_file (file_data->file, file_data->info, NULL);
+}
+
+
+static void
+gth_metadata_provider_gstreamer_finalize (GObject *object)
+{
+ /*GthMetadataProviderGstreamer *comment = GTH_METADATA_PROVIDER_GSTREAMER (object);*/
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GObject *
+gth_metadata_provider_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GthMetadataProviderClass *klass;
+ GObjectClass *parent_class;
+ GObject *obj;
+ GthMetadataProvider *self;
+
+ klass = GTH_METADATA_PROVIDER_CLASS (g_type_class_peek (GTH_TYPE_METADATA_PROVIDER));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ obj = parent_class->constructor (type, n_construct_properties, construct_properties);
+ self = GTH_METADATA_PROVIDER (obj);
+
+ g_object_set (self, "readable-attributes", "audio-video::*", NULL);
+
+ return obj;
+}
+
+
+static void
+gth_metadata_provider_gstreamer_class_init (GthMetadataProviderGstreamerClass *klass)
+{
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GthMetadataProviderGstreamerPrivate));
+
+ G_OBJECT_CLASS (klass)->finalize = gth_metadata_provider_gstreamer_finalize;
+ G_OBJECT_CLASS (klass)->constructor = gth_metadata_provider_constructor;
+
+ GTH_METADATA_PROVIDER_CLASS (klass)->read = gth_metadata_provider_gstreamer_read;
+}
+
+
+static void
+gth_metadata_provider_gstreamer_init (GthMetadataProviderGstreamer *catalogs)
+{
+}
+
+
+GType
+gth_metadata_provider_gstreamer_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo type_info = {
+ sizeof (GthMetadataProviderGstreamerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gth_metadata_provider_gstreamer_class_init,
+ NULL,
+ NULL,
+ sizeof (GthMetadataProviderGstreamer),
+ 0,
+ (GInstanceInitFunc) gth_metadata_provider_gstreamer_init
+ };
+
+ type = g_type_register_static (GTH_TYPE_METADATA_PROVIDER,
+ "GthMetadataProviderGstreamer",
+ &type_info,
+ 0);
+ }
+
+ return type;
+}
diff --git a/extensions/gstreamer/gth-metadata-provider-gstreamer.h b/extensions/gstreamer/gth-metadata-provider-gstreamer.h
new file mode 100644
index 0000000..58c3337
--- /dev/null
+++ b/extensions/gstreamer/gth-metadata-provider-gstreamer.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_METADATA_PROVIDER_GSTREAMER_H
+#define GTH_METADATA_PROVIDER_GSTREAMER_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gthumb.h>
+
+#define GTH_TYPE_METADATA_PROVIDER_GSTREAMER (gth_metadata_provider_gstreamer_get_type ())
+#define GTH_METADATA_PROVIDER_GSTREAMER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_METADATA_PROVIDER_GSTREAMER, GthMetadataProviderGstreamer))
+#define GTH_METADATA_PROVIDER_GSTREAMER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_METADATA_PROVIDER_GSTREAMER, GthMetadataProviderGstreamerClass))
+#define GTH_IS_METADATA_PROVIDER_GSTREAMER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_METADATA_PROVIDER_GSTREAMER))
+#define GTH_IS_METADATA_PROVIDER_GSTREAMER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_METADATA_PROVIDER_GSTREAMER))
+#define GTH_METADATA_PROVIDER_GSTREAMER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_METADATA_PROVIDER_GSTREAMER, GthMetadataProviderGstreamerClass))
+
+typedef struct _GthMetadataProviderGstreamer GthMetadataProviderGstreamer;
+typedef struct _GthMetadataProviderGstreamerPrivate GthMetadataProviderGstreamerPrivate;
+typedef struct _GthMetadataProviderGstreamerClass GthMetadataProviderGstreamerClass;
+
+struct _GthMetadataProviderGstreamer
+{
+ GthMetadataProvider __parent;
+ GthMetadataProviderGstreamerPrivate *priv;
+};
+
+struct _GthMetadataProviderGstreamerClass
+{
+ GthMetadataProviderClass __parent_class;
+};
+
+GType gth_metadata_provider_gstreamer_get_type (void) G_GNUC_CONST;
+
+#endif /* GTH_METADATA_PROVIDER_GSTREAMER_H */
diff --git a/extensions/gstreamer/main.c b/extensions/gstreamer/main.c
new file mode 100644
index 0000000..0465225
--- /dev/null
+++ b/extensions/gstreamer/main.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gthumb.h>
+#include "gth-metadata-provider-gstreamer.h"
+
+
+GthMetadataCategory gstreamer_metadata_category[] = {
+ { "audio-video::general", N_("General"), 30 },
+ { "audio-video::video", N_("Video"), 40 },
+ { "audio-video::audio", N_("Audio"), 50 },
+ { "audio-video::other", N_("Other"), 60 },
+ { NULL, NULL, 0 }
+};
+
+
+GthMetadataInfo gstreamer_metadata_info[] = {
+ { "audio-video::general::title", N_("Title"), "audio-video::general", 1, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::general::artist", N_("Artist"), "audio-video::general", 2, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::general::album", N_("Album"), "audio-video::general", 3, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::general::duration", N_("Duration"), "audio-video::general", 4, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::general::container-format", N_("Container Format"), "audio-video::general", 5, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::general::encoder", N_("Encoder"), "audio-video::general", 6, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+
+ { "audio-video::video::size", N_("Dimensions"), "audio-video::video", 1, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::video::codec", N_("Codec"), "audio-video::video", 2, GTH_METADATA_ALLOW_EVERYWHERE },
+ { "audio-video::video::framerate", N_("Framerate"), "audio-video::video", 3, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::video::bitrate", N_("Bitrate"), "audio-video::video", 4, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::video::width", N_("Width"), "audio-video::video", 0, GTH_METADATA_ALLOW_NOWHERE },
+ { "audio-video::video::height", N_("Height"), "audio-video::video", 0, GTH_METADATA_ALLOW_NOWHERE },
+
+ { "audio-video::audio::codec", N_("Codec"), "audio-video::audio", 1, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::audio::channels", N_("Channels"), "audio-video::audio", 2, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::audio::samplerate", N_("Sample rate"), "audio-video::audio", 3, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+ { "audio-video::audio::bitrate", N_("Bitrate"), "audio-video::audio", 4, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+
+ { NULL, NULL, NULL, 0, 0 }
+};
+
+
+G_MODULE_EXPORT void
+gthumb_extension_activate (void)
+{
+ gth_main_register_metadata_category (gstreamer_metadata_category);
+ gth_main_register_metadata_info_v (gstreamer_metadata_info);
+ gth_main_register_metadata_provider (GTH_TYPE_METADATA_PROVIDER_GSTREAMER);
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_deactivate (void)
+{
+}
+
+
+G_MODULE_EXPORT gboolean
+gthumb_extension_is_configurable (void)
+{
+ return FALSE;
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_configure (GtkWindow *parent)
+{
+}
diff --git a/extensions/image_viewer/main.c b/extensions/image_viewer/main.c
index 5bd8a24..2536443 100644
--- a/extensions/image_viewer/main.c
+++ b/extensions/image_viewer/main.c
@@ -36,7 +36,7 @@ GthMetadataCategory image_metadata_category[] = {
GthMetadataInfo image_metadata_info[] = {
- { "image::size", N_("Image Size"), "image", 1, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW | GTH_METADATA_ALLOW_IN_FILE_LIST },
+ { "image::size", N_("Dimensions"), "image", 1, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW | GTH_METADATA_ALLOW_IN_FILE_LIST },
{ "image::format", N_("Format"), "image", 2, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
{ NULL, NULL, NULL, 0, 0 }
};
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 2b7e80a..388a701 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -239,6 +239,7 @@ gthumb_LDADD = \
$(JPEG_LIBS) \
$(TIFF_LIBS) \
$(CLUTTER_LIBS) \
+ $(GSTREAMER_LIBS) \
$(NULL)
if RUN_IN_PLACE
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]