[tracker/tracker-0.6] Fixes NB#114880, tracker-extract crashed while extracting a video
- From: Mikael Ottela <mottela src gnome org>
- To: svn-commits-list gnome org
- Subject: [tracker/tracker-0.6] Fixes NB#114880, tracker-extract crashed while extracting a video
- Date: Thu, 4 Jun 2009 07:03:29 -0400 (EDT)
commit adec109125d9e709657054d0ac9d7c86ee064042
Author: Mikael Ottela <mikael ottela ixonos com>
Date: Thu Jun 4 13:31:29 2009 +0300
Fixes NB#114880, tracker-extract crashed while extracting a video
Fixes NB#95873, duration not extracted for mp2 and aac files
Fixes NB#96142, Video library : Duration of the Video clips is not displaying.
The gstreamer extractor has been changed to use the new implementation of
tagreadbin if available.
---
configure.ac | 16 +-
src/tracker-extract/tracker-extract-gstreamer.c | 688 ++++++++++++-----------
2 files changed, 373 insertions(+), 331 deletions(-)
diff --git a/configure.ac b/configure.ac
index 6de0b91..48854b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -347,6 +347,20 @@ if test "x$enable_detailed_metadata" != "xno"; then
AC_DEFINE(ENABLE_DETAILED_METADATA, 1, [Define if we want detailed metadata in the database])
fi
+####################################################################
+# Use tagreadbin in gstreamer extraction?
+####################################################################
+
+AC_ARG_ENABLE(gstreamer-tagreadbin,
+ AS_HELP_STRING([--enable-gstreamer-tagreadbin],
+ [enable tagreadbin in gstreamer [[default=no]]]),
+ [enable_tagreadbin=yes],
+ [enable_tagreadbin=no])
+
+if test "x$enable_tagreadbin" != "xno"; then
+ AC_DEFINE(TRACKER_EXTRACT_GSTREAMER_USE_TAGREADBIN, 1, [Use tagreadbin in gstreamer extraction])
+fi
+
##################################################################
# Check for HAL
##################################################################
@@ -1484,7 +1498,7 @@ Metadata Extractors:
Support MS & Open Office: $have_libgsf
Support XML / HTML: $have_libxml2
Support embedded / sidecar XMP: $have_exempi
- Support video formats: $have_video_handler ($have_video_handler_app)
+ Support video formats: $have_video_handler ($have_video_handler_app) (tagreadbin: $enable_tagreadbin)
Support helix formats (RPM/RM/etc): $have_gstreamer_helix
Support MP3 album art (w/ GdkPixbuf): $have_gdkpixbuf
Support playlists (w/ Totem): $have_playlist
diff --git a/src/tracker-extract/tracker-extract-gstreamer.c b/src/tracker-extract/tracker-extract-gstreamer.c
index a1f3fe8..6d6b6ce 100644
--- a/src/tracker-extract/tracker-extract-gstreamer.c
+++ b/src/tracker-extract/tracker-extract-gstreamer.c
@@ -46,6 +46,31 @@
#define GST_TAG_CLASSIFICATION "classification"
#endif
+/* Some additional tagreadbin tags (FIXME until they are defined upstream)*/
+#ifndef GST_TAG_CHANNEL
+#define GST_TAG_CHANNEL "channel"
+#endif
+
+#ifndef GST_TAG_RATE
+#define GST_TAG_RATE "rate"
+#endif
+
+#ifndef GST_TAG_WIDTH
+#define GST_TAG_WIDTH "width"
+#endif
+
+#ifndef GST_TAG_HEIGHT
+#define GST_TAG_HEIGHT "height"
+#endif
+
+#ifndef GST_TAG_PIXEL_RATIO
+#define GST_TAG_PIXEL_RATIO "pixel-aspect-ratio"
+#endif
+
+#ifndef GST_TAG_FRAMERATE
+#define GST_TAG_FRAMERATE "framerate"
+#endif
+
typedef enum {
EXTRACT_MIME_UNDEFINED,
EXTRACT_MIME_AUDIO,
@@ -54,27 +79,17 @@ typedef enum {
} ExtractMime;
typedef struct {
- /* Pipeline elements */
- GMainLoop *loop;
-
- GstElement *bin;
- GstElement *filesrc;
- GstElement *cache;
+ /* Common pipeline elements */
GstElement *pipeline;
GstBus *bus;
- guint id;
-
- GList *fsinks;
ExtractMime mime;
- /* Tags and data */
- GstTagList *tagcache;
-
- GstTagList *audiotags;
- GstTagList *videotags;
+ /* Decodebin elements and properties*/
+ GstElement *bin;
+ GList *fsinks;
gint64 duration;
gint video_height;
@@ -84,16 +99,15 @@ typedef struct {
gint audio_channels;
gint audio_samplerate;
+ /* Tags and data */
+ GstTagList *tagcache;
+
unsigned char *album_art_data;
guint album_art_size;
const gchar *album_art_mime;
} MetadataExtractor;
-/* FIXME Make these definable/dynamic at some point */
-const guint use_dbin = 1;
-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);
@@ -105,6 +119,13 @@ static TrackerExtractData data[] = {
{ NULL, NULL }
};
+/* Not using define directly since we might want to make this dynamic */
+#ifdef TRACKER_EXTRACT_GSTREAMER_USE_TAGREADBIN
+const gboolean use_tagreadbin = TRUE;
+#else
+const gboolean use_tagreadbin = FALSE;
+#endif
+
static void
add_int64_info (GHashTable *metadata,
gchar *key,
@@ -169,6 +190,24 @@ add_uint_gst_tag (GHashTable *metadata,
}
static void
+add_int_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ gint n;
+
+ ret = gst_tag_list_get_int (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,
@@ -187,6 +226,28 @@ add_double_gst_tag (GHashTable *metadata,
}
static void
+add_fraction_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ GValue n = {0,};
+ gfloat f;
+
+ ret = gst_tag_list_copy_value (&n, tag_list, tag);
+
+ f = (gfloat)gst_value_get_fraction_numerator (&n)/
+ gst_value_get_fraction_denominator (&n);
+
+ if (ret) {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata_printf ("%f", f));
+ }
+}
+
+static void
add_y_date_gst_tag (GHashTable *metadata,
const gchar *key,
GstTagList *tag_list,
@@ -213,26 +274,21 @@ add_y_date_gst_tag (GHashTable *metadata,
}
}
-static gint64
-get_media_duration (MetadataExtractor *extractor)
+static void
+add_time_gst_tag (GHashTable *metadata,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
{
- gint64 duration;
- GstFormat fmt;
-
- g_return_val_if_fail (extractor, -1);
- g_return_val_if_fail (extractor->pipeline, -1);
+ gboolean ret;
+ guint64 n;
- fmt = GST_FORMAT_TIME;
+ ret = gst_tag_list_get_uint64 (tag_list, tag, &n);
- duration = -1;
-
- if (gst_element_query_duration (extractor->pipeline,
- &fmt,
- &duration) &&
- duration >= 0) {
- return duration / GST_SECOND;
- } else {
- return -1;
+ if (ret) {
+ g_hash_table_insert (metadata,
+ g_strdup (key),
+ tracker_escape_metadata_printf ("%lld", n/GST_SECOND));
}
}
@@ -278,61 +334,41 @@ get_embedded_album_art(MetadataExtractor *extractor)
}
static void
-extract_metadata (MetadataExtractor *extractor,
- GHashTable *metadata)
+extract_stream_metadata_tagreadbin (MetadataExtractor *extractor,
+ GHashTable *metadata)
{
- gchar *value;
-
- g_return_if_fail (extractor != NULL);
- g_return_if_fail (metadata != NULL);
-
- 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);
#ifdef ENABLE_DETAILED_METADATA
- add_string_gst_tag (metadata, "DC:Coverage", extractor->tagcache, GST_TAG_LOCATION);
+ add_uint_gst_tag (metadata, "Audio:Channels", extractor->tagcache, GST_TAG_CHANNEL);
+ add_uint_gst_tag (metadata, "Audio:Samplerate", extractor->tagcache, GST_TAG_RATE);
#endif /* ENABLE_DETAILED_METADATA */
- /* 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);
-#ifdef ENABLE_DETAILED_METADATA
- 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);
-#endif /* ENABLE_DETAILED_METADATA */
- 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);
-#ifdef ENABLE_DETAILED_METADATA
- add_string_gst_tag (metadata, "Audio:Codec", extractor->tagcache, GST_TAG_AUDIO_CODEC);
-#endif /* ENABLE_DETAILED_METADATA */
+ if (extractor->mime == EXTRACT_MIME_IMAGE) {
+ add_int_gst_tag (metadata, "Image:Height", extractor->tagcache, GST_TAG_HEIGHT);
+ } else {
+ add_int_gst_tag (metadata, "Video:Height", extractor->tagcache, GST_TAG_HEIGHT);
+ }
- /* Video */
- add_string_gst_tag (metadata, "Video:Codec", extractor->tagcache, GST_TAG_VIDEO_CODEC);
+ if (extractor->mime == EXTRACT_MIME_IMAGE) {
+ add_int_gst_tag (metadata, "Image:Width", extractor->tagcache, GST_TAG_WIDTH);
+ } else {
+ add_int_gst_tag (metadata, "Video:Width", extractor->tagcache, GST_TAG_WIDTH);
+ }
- 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:Creator", 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, "Video:Source", extractor->tagcache, GST_TAG_CLASSIFICATION);
- } 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);
-#ifdef ENABLE_DETAILED_METADATA
- add_string_gst_tag (metadata, "Audio:Comment", extractor->tagcache, GST_TAG_COMMENT);
-#endif /* ENABLE_DETAILED_METADATA */
- }
+ if (extractor->mime == EXTRACT_MIME_VIDEO) {
+ add_fraction_gst_tag (metadata, "Video:Framerate", extractor->tagcache, GST_TAG_FRAMERATE);
+
+ add_time_gst_tag (metadata, "Video:Duration", extractor->tagcache, GST_TAG_DURATION);
+ } else if (extractor->mime == EXTRACT_MIME_AUDIO) {
+ add_time_gst_tag (metadata, "Audio:Duration", extractor->tagcache, GST_TAG_DURATION);
+
+ get_embedded_album_art (extractor);
}
+}
+static void
+extract_stream_metadata_decodebin (MetadataExtractor *extractor,
+ GHashTable *metadata)
+{
#ifdef ENABLE_DETAILED_METADATA
if (extractor->audio_channels >= 0) {
add_uint_info (metadata,
@@ -388,13 +424,68 @@ extract_metadata (MetadataExtractor *extractor,
get_embedded_album_art (extractor);
}
+}
- if (extractor->audiotags) {
- add_uint_gst_tag (metadata, "Audio:Bitrate", extractor->audiotags, GST_TAG_BITRATE);
- }
+static void
+extract_metadata (MetadataExtractor *extractor,
+ GHashTable *metadata)
+{
+ gchar *value;
+
+ g_return_if_fail (extractor != NULL);
+ g_return_if_fail (metadata != NULL);
- if (extractor->videotags) {
- add_uint_gst_tag (metadata, "Video:Bitrate", extractor->videotags, GST_TAG_BITRATE);
+ 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);
+#ifdef ENABLE_DETAILED_METADATA
+ add_string_gst_tag (metadata, "DC:Coverage", extractor->tagcache, GST_TAG_LOCATION);
+#endif /* ENABLE_DETAILED_METADATA */
+
+ /* 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);
+#ifdef ENABLE_DETAILED_METADATA
+ 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);
+#endif /* ENABLE_DETAILED_METADATA */
+ 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);
+#ifdef ENABLE_DETAILED_METADATA
+ add_string_gst_tag (metadata, "Audio:Codec", extractor->tagcache, GST_TAG_AUDIO_CODEC);
+#endif /* ENABLE_DETAILED_METADATA */
+
+ /* 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:Creator", 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, "Video:Source", extractor->tagcache, GST_TAG_CLASSIFICATION);
+ } 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);
+#ifdef ENABLE_DETAILED_METADATA
+ add_string_gst_tag (metadata, "Audio:Comment", extractor->tagcache, GST_TAG_COMMENT);
+#endif /* ENABLE_DETAILED_METADATA */
+ }
+ }
+
+ if (use_tagreadbin) {
+ extract_stream_metadata_tagreadbin (extractor, metadata);
+ } else {
+ extract_stream_metadata_decodebin (extractor, metadata);
}
/* Do some postprocessing (FIXME, or fix gstreamer) */
@@ -427,8 +518,9 @@ dbin_dpad_cb (GstElement* e, GstPad* pad, gboolean cont, gpointer data)
fsink = gst_element_factory_make ("fakesink", NULL);
+ /* We increase the preroll buffer so we get duration (one frame not enough)*/
g_value_init (&val, G_TYPE_INT);
- g_value_set_int (&val, 50);
+ g_value_set_int (&val, 51);
g_object_set_property (G_OBJECT (fsink), "preroll-queue-len", &val);
g_value_unset (&val);
@@ -441,94 +533,27 @@ dbin_dpad_cb (GstElement* e, GstPad* pad, gboolean cont, gpointer data)
gst_object_unref (fsinkpad);
}
-static void
-add_stream_tags_tagreadbin_for_element (MetadataExtractor *extractor,
- GstElement *elem)
+static guint64
+get_media_duration (MetadataExtractor *extractor)
{
- GstStructure *s = NULL;
- GstCaps *caps = NULL;
- GstIterator *iter = NULL;
- gboolean done = FALSE;
- gpointer item;
-
- iter = gst_element_iterate_sink_pads (elem);
-
- while (!done) {
- switch (gst_iterator_next (iter, &item)) {
- case GST_ITERATOR_OK:
- if ((caps = GST_PAD_CAPS (item))) {
- s = gst_caps_get_structure (caps, 0);
-
- if (s) {
- if (g_strrstr (gst_structure_get_name (s), "audio")) {
- if ( ( (extractor->audio_channels != -1) &&
- (extractor->audio_samplerate != -1) ) ||
- !( (gst_structure_get_int (s,
- "channels",
- &extractor->audio_channels) ) &&
- (gst_structure_get_int (s,
- "rate",
- &extractor->audio_samplerate)) ) ) {
- return;
- }
- } else if (g_strrstr (gst_structure_get_name (s), "video")) {
- if ( ( (extractor->video_fps_n != -1) &&
- (extractor->video_fps_d != -1) &&
- (extractor->video_width != -1) &&
- (extractor->video_height != -1) ) ||
- !( (gst_structure_get_fraction (s,
- "framerate",
- &extractor->video_fps_n,
- &extractor->video_fps_d) ) &&
- (gst_structure_get_int (s, "width", &extractor->video_width)) &&
- (gst_structure_get_int (s, "height", &extractor->video_height)))) {
- return;
- }
- }
- }
- }
- gst_object_unref (item);
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- }
- }
- gst_iterator_free (iter);
-}
+ gint64 duration;
+ GstFormat fmt;
-/* FIXME This is a temporary solution while tagreadbin does not support pad signals */
+ g_return_val_if_fail (extractor, -1);
+ g_return_val_if_fail (extractor->pipeline, -1);
-static void
-add_stream_tags_tagreadbin (MetadataExtractor *extractor)
-{
- GstIterator *iter = NULL;
- gboolean done = FALSE;
- gpointer item;
+ fmt = GST_FORMAT_TIME;
- iter = gst_bin_iterate_elements (GST_BIN(extractor->bin));
+ duration = -1;
- while (!done) {
- switch (gst_iterator_next (iter, &item)) {
- case GST_ITERATOR_OK:
- add_stream_tags_tagreadbin_for_element (extractor, item);
- g_object_unref (item);
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- }
+ if (gst_element_query_duration (extractor->pipeline,
+ &fmt,
+ &duration) &&
+ duration >= 0) {
+ return duration / GST_SECOND;
+ } else {
+ return -1;
}
-
- gst_iterator_free (iter);
}
static void
@@ -577,23 +602,14 @@ static void
add_stream_tags (MetadataExtractor *extractor)
{
extractor->duration = get_media_duration (extractor);
-
- if (use_dbin) {
- g_list_foreach (extractor->fsinks, add_stream_tag, extractor);
- } else {
- add_stream_tags_tagreadbin (extractor);
- }
+ g_list_foreach (extractor->fsinks, add_stream_tag, extractor);
}
static void
-add_tags (GstMessage *msg, MetadataExtractor *extractor)
+add_tags (GstTagList *new_tags, MetadataExtractor *extractor)
{
- GstPad *pad;
- 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);
@@ -603,97 +619,159 @@ add_tags (GstMessage *msg, MetadataExtractor *extractor)
}
extractor->tagcache = result;
+}
- /* media-type-specific tags */
- if (GST_IS_ELEMENT (msg->src) &&
- (pad = gst_element_get_static_pad (GST_ELEMENT (msg->src), "sink"))) {
- GstTagList **cache;
- const GstStructure *s;
- GstCaps *caps;
- cache = NULL;
-
- caps = gst_pad_get_caps (pad);
- s = gst_caps_get_structure (caps, 0);
+static gboolean
+poll_for_ready (MetadataExtractor *extractor,
+ GstState state,
+ gboolean ready_with_state,
+ gboolean ready_with_eos)
+{
+ gint64 timeout = 5 * GST_SECOND;
+ GstBus *bus = extractor->bus;
+ GstTagList *new_tags;
+
+ gst_element_set_state (extractor->pipeline, state);
- if (g_strrstr (gst_structure_get_name(s), "audio")) {
- cache = &extractor->audiotags;
- } else if (g_strrstr (gst_structure_get_name(s), "video")) {
- cache = &extractor->videotags;
+ while (TRUE) {
+ GstMessage *message;
+ GstElement *src;
+
+ message = gst_bus_timed_pop (bus, timeout);
+
+ if (!message) {
+ g_warning ("Pipeline timed out");
+ return FALSE;
}
- if (cache) {
- result = gst_tag_list_merge (*cache,
- new_tags,
- GST_TAG_MERGE_KEEP);
- if (*cache) {
- gst_tag_list_free (*cache);
+ src = (GstElement*)GST_MESSAGE_SRC (message);
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_STATE_CHANGED: {
+ if (ready_with_state) {
+ GstState old, new, pending;
+
+ if (src == extractor->pipeline) {
+ gst_message_parse_state_changed (message, &old, &new, &pending);
+ if (new == state) {
+ gst_message_unref (message);
+ return TRUE;
+ }
+ }
}
-
- *cache = result;
+ break;
}
+ case GST_MESSAGE_ERROR: {
+ GError *lerror = NULL;
+ gchar *error_message;
- gst_caps_unref (caps);
+ gst_message_parse_error (message, &lerror, &error_message);
+ gst_message_unref (message);
+ g_warning ("Got error :%s", error_message);
+ g_free (error_message);
+ g_error_free (lerror);
+
+ return FALSE;
+ break;
+ }
+ case GST_MESSAGE_EOS: {
+ gst_message_unref (message);
+
+ if (ready_with_eos) {
+ return TRUE;
+ } else {
+ g_warning ("Reached end-of-file without proper content");
+ return FALSE;
+ }
+ break;
+ }
+ case GST_MESSAGE_TAG: {
+ gst_message_parse_tag (message, &new_tags);
+ add_tags (new_tags, extractor);
+ gst_tag_list_free (new_tags);
+ break;
+ }
+ default:
+ /* Nothing to do here */
+ break;
+ }
+
+ gst_message_unref (message);
}
- gst_tag_list_free (new_tags);
+ g_assert_not_reached ();
+
+ return FALSE;
}
-static gboolean
-metadata_bus_async_cb (GstBus *bus, GstMessage *msg, gpointer data)
+static GstElement *
+create_decodebin_pipeline (MetadataExtractor *extractor, const gchar *uri)
{
- MetadataExtractor *extractor = (MetadataExtractor *)data;
- GError *error = NULL;
- gboolean stop = FALSE;
+ GstElement *pipeline = NULL;
- 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 (sender == extractor->pipeline) {
- GstState newstate;
- GstState oldstate;
- gst_message_parse_state_changed (msg, &oldstate, &newstate, NULL);
- if ((oldstate == GST_STATE_READY) && (newstate == GST_STATE_PAUSED)) {
- stop = TRUE;
- }
- }
- }
- break;
- case GST_MESSAGE_DURATION:
- /* The reasoning here is that if we already got duration we should have also
- all the other data we need since getting the duration should take the longest */
- stop = TRUE;
- break;
- default:
- break;
+ GstElement *filesrc = NULL;
+ GstElement *bin = NULL;
+
+ guint id;
+
+ pipeline = gst_element_factory_make ("pipeline", NULL);
+ if (!pipeline) {
+ g_warning ("Failed to create GStreamer pipeline");
+ return FALSE;
}
-
- if (stop) {
- add_stream_tags(extractor);
- 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);
+
+ filesrc = gst_element_factory_make ("filesrc", NULL);
+ if (!filesrc) {
+ g_warning ("Failed to create GStreamer filesrc");
+ return FALSE;
+ }
+
+ bin = gst_element_factory_make ("decodebin2", "decodebin2");
+ if (!bin) {
+ g_warning ("Failed to create GStreamer decodebin");
+ return FALSE;
}
+
+ id = g_signal_connect (G_OBJECT (bin),
+ "new-decoded-pad",
+ G_CALLBACK (dbin_dpad_cb),
+ extractor);
- return TRUE;
+ gst_bin_add (GST_BIN (pipeline), filesrc);
+ gst_bin_add (GST_BIN (pipeline), bin);
+
+ if (!gst_element_link_many (filesrc, bin, NULL)) {
+ g_warning ("Could not link GStreamer elements");
+ return FALSE;
+ }
+
+ g_object_set (G_OBJECT (filesrc), "location", uri, NULL);
+
+ extractor->bin = bin;
+
+ return pipeline;
}
+static GstElement *
+create_tagreadbin_pipeline (MetadataExtractor *extractor, const gchar *uri)
+{
+ GstElement *pipeline = NULL;
+ gchar *complete_uri = NULL;
+
+ pipeline = gst_element_factory_make ("tagreadbin", "tagreadbin");
+ if (!pipeline) {
+ g_warning ("Failed to create GStreamer tagreadbin");
+ return NULL;
+ }
+
+ complete_uri = g_build_filename ("file://", uri, NULL);
+ g_object_set (G_OBJECT (pipeline), "uri", complete_uri, NULL);
+ g_free (complete_uri);
+ return pipeline;
+}
+
+
static void
tracker_extract_gstreamer (const gchar *uri,
GHashTable *metadata,
@@ -709,98 +787,57 @@ tracker_extract_gstreamer (const gchar *uri,
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->pipeline = NULL;
extractor->bus = NULL;
- extractor->id = 0;
-
- extractor->fsinks = NULL;
-
extractor->mime = type;
extractor->tagcache = NULL;
- extractor->audiotags = NULL;
- extractor->videotags = NULL;
-
extractor->album_art_data = NULL;
extractor->album_art_size = 0;
extractor->album_art_mime = NULL;
+ extractor->bin = NULL;
+ extractor->fsinks = NULL;
+
extractor->duration = -1;
extractor->video_fps_n = extractor->video_fps_d = -1;
extractor->video_height = extractor->video_width = -1;
extractor->audio_channels = -1;
extractor->audio_samplerate = -1;
-
- extractor->pipeline = gst_element_factory_make ("pipeline", NULL);
- if (!extractor->pipeline) {
- g_critical ("Failed to create GStreamer pipeline");
- goto fail;
+
+ if (use_tagreadbin) {
+ extractor->pipeline = create_tagreadbin_pipeline (extractor, uri);
+ } else {
+ extractor->pipeline = create_decodebin_pipeline (extractor, uri);
}
- extractor->filesrc = gst_element_factory_make ("filesrc", NULL);
- if (!extractor->filesrc) {
- g_critical ("Failed to create GStreamer filesrc");
+
+ if (!extractor->pipeline) {
+ g_warning ("No valid pipeline for uri %s", uri);
goto fail;
}
- if (use_cache) {
- extractor->cache = gst_element_factory_make ("cache", NULL);
- if (!extractor->cache) {
- g_critical ("Failed to create GStreamer cache");
- goto fail;
- }
- }
- if (use_dbin) {
- extractor->bin = gst_element_factory_make ("decodebin2", "decodebin2");
- if (!extractor->bin) {
- g_critical ("Failed to create GStreamer decodebin");
- goto fail;
- }
- extractor->id = g_signal_connect (G_OBJECT (extractor->bin),
- "new-decoded-pad",
- G_CALLBACK (dbin_dpad_cb),
- extractor);
- } else {
- extractor->bin = gst_element_factory_make ("tagreadbin", "tagreadbin");
- if (!extractor->bin) {
- g_error ("Failed to create GStreamer tagreadbin");
- goto fail;
- }
- 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_critical ("Could not link GStreamer elements (using cache)");
- /* FIXME Clean up */
+ extractor->bus = gst_pipeline_get_bus (GST_PIPELINE (extractor->pipeline));
+
+ if (use_tagreadbin) {
+ if (!poll_for_ready (extractor, GST_STATE_PLAYING, FALSE, TRUE)) {
+ g_warning ("Error running tagreadbin");
goto fail;
- }
+ }
} else {
- if (!gst_element_link_many (extractor->filesrc, extractor->bin, NULL)) {
- g_critical ("Could not link GStreamer elements");
- /* FIXME Clean up */
+ if (!poll_for_ready (extractor, GST_STATE_PAUSED, TRUE, FALSE)) {
+ g_warning ("Error running decodebin");
goto fail;
}
- }
- 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);
-
- 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);
+ add_stream_tags(extractor);
+ 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;
+ }
extract_metadata (extractor, metadata);
@@ -830,16 +867,7 @@ tracker_extract_gstreamer (const gchar *uri,
gst_tag_list_free (extractor->tagcache);
}
- if (extractor->audiotags) {
- gst_tag_list_free (extractor->audiotags);
- }
-
- if (extractor->videotags) {
- gst_tag_list_free (extractor->videotags);
- }
-
gst_object_unref (GST_OBJECT (extractor->pipeline));
- g_main_loop_unref (extractor->loop);
g_slice_free (MetadataExtractor, extractor);
fail:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]