From 1b26e5c642e946236207bf0784bf496c7d193e25 Mon Sep 17 00:00:00 2001 From: Jens Georg Date: Wed, 23 Sep 2009 15:35:43 +0200 Subject: [PATCH] core: be more robust while scanning metadata - Add a timeout to check for stuck/aborted scannings - Don't reuse playbin, this seems to be problematic --- src/rygel/rygel-metadata-extractor.vala | 69 +++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/rygel/rygel-metadata-extractor.vala b/src/rygel/rygel-metadata-extractor.vala index 4f71816..84414d7 100644 --- a/src/rygel/rygel-metadata-extractor.vala +++ b/src/rygel/rygel-metadata-extractor.vala @@ -64,7 +64,8 @@ public class Rygel.MetadataExtractor: GLib.Object { private TagList tag_list; private GLib.Queue file_queue; - private Gst.Element[] fakesinks; + + private uint timeout_id; private static void register_custom_tag (string tag, Type type) { Gst.tag_register (tag, @@ -75,34 +76,40 @@ public class Rygel.MetadataExtractor: GLib.Object { Gst.tag_merge_use_first); } - public MetadataExtractor () { - this.register_custom_tag (TAG_RYGEL_SIZE, typeof (int64)); - this.register_custom_tag (TAG_RYGEL_DURATION, typeof (int64)); - this.register_custom_tag (TAG_RYGEL_MIME, typeof (string)); - this.register_custom_tag (TAG_RYGEL_CHANNELS, typeof (int)); - this.register_custom_tag (TAG_RYGEL_RATE, typeof (int)); - this.register_custom_tag (TAG_RYGEL_WIDTH, typeof (int)); - this.register_custom_tag (TAG_RYGEL_HEIGHT, typeof (int)); - this.register_custom_tag (TAG_RYGEL_DEPTH, typeof (int)); - this.register_custom_tag (TAG_RYGEL_MTIME, typeof (uint64)); - + private void renew_playbin () { // setup fake sinks this.playbin = ElementFactory.make ("playbin2", null); if (this.playbin == null) { this.playbin = ElementFactory.make ("playbin", null); } - this.fakesinks = new Gst.Element[2]; - this.fakesinks[0] = ElementFactory.make ("fakesink", null); - this.fakesinks[1] = ElementFactory.make ("fakesink", null); - this.playbin.video_sink = this.fakesinks[0]; - this.playbin.audio_sink = this.fakesinks[1]; + // increase reference count of sinks to workaround + // bug #596078 + var sink = ElementFactory.make ("fakesink", null); + sink.ref (); + this.playbin.video_sink = sink; + + sink = ElementFactory.make ("fakesink", null); + sink.ref (); + this.playbin.audio_sink = sink; var bus = this.playbin.get_bus (); bus.add_signal_watch (); bus.message["tag"] += this.tag_cb; bus.message["state-changed"] += this.state_changed_cb; bus.message["error"] += this.error_cb; + } + + public MetadataExtractor () { + this.register_custom_tag (TAG_RYGEL_SIZE, typeof (int64)); + this.register_custom_tag (TAG_RYGEL_DURATION, typeof (int64)); + this.register_custom_tag (TAG_RYGEL_MIME, typeof (string)); + this.register_custom_tag (TAG_RYGEL_CHANNELS, typeof (int)); + this.register_custom_tag (TAG_RYGEL_RATE, typeof (int)); + this.register_custom_tag (TAG_RYGEL_WIDTH, typeof (int)); + this.register_custom_tag (TAG_RYGEL_HEIGHT, typeof (int)); + this.register_custom_tag (TAG_RYGEL_DEPTH, typeof (int)); + this.register_custom_tag (TAG_RYGEL_MTIME, typeof (uint64)); this.file_queue = new GLib.Queue (); this.tag_list = new Gst.TagList (); @@ -116,12 +123,34 @@ public class Rygel.MetadataExtractor: GLib.Object { } } + private bool on_harvesting_timeout () { + warning ("Metadata extractor timed out on %s, restarting", + this.file_queue.peek_head ().get_uri ()); + this.playbin.set_state (State.NULL); + + this.error (file_queue.peek_head (), + new IOChannelError.FAILED ("Pipeline stuck while reading file info")); + this.file_queue.pop_head (); + extract_next (); + return false; + } + private void extract_next () { + if (this.timeout_id != 0) + Source.remove (this.timeout_id); + if (this.file_queue.get_length () > 0) { try { var item = this.file_queue.peek_head (); - this.extract_mime_and_size (); + debug ("Scheduling file %s for metadata extraction", + item.get_uri ()); + this.extract_mime_and_size (); + renew_playbin (); this.playbin.uri = item.get_uri (); + this.timeout_id = Timeout.add_seconds_full ( + Priority.DEFAULT, + 5, + on_harvesting_timeout); this.playbin.set_state (State.PAUSED); } catch (Error error) { // on error just move to the next uri in queue @@ -241,9 +270,9 @@ public class Rygel.MetadataExtractor: GLib.Object { } private void extract_stream_info () { - extract_av_info (this.fakesinks[0].get_pad ("sink"), + extract_av_info (this.playbin.video_sink.get_pad ("sink"), StreamType.VIDEO); - extract_av_info (this.fakesinks[1].get_pad ("sink"), + extract_av_info (this.playbin.audio_sink.get_pad ("sink"), StreamType.AUDIO); } -- 2.7.4