From 45ee4d534a948a15427ac140f340ad2963646375 Mon Sep 17 00:00:00 2001 From: "Zeeshan Ali (Khattak)" Date: Wed, 21 Jul 2010 21:18:51 +0300 Subject: [PATCH] media-export: Simplify metadata extraction code We don't need to transform the metadata into Gst.TagList to be able to make use of it so this should not only simplify the code but also optimize the extraction process. Based on a patch from Arun Raghavan . --- .../media-export/rygel-media-export-harvester.vala | 17 +- .../media-export/rygel-media-export-item.vala | 285 ++++++++++++--------- .../rygel-media-export-metadata-extractor.vala | 119 ++------- 3 files changed, 193 insertions(+), 228 deletions(-) diff --git a/src/plugins/media-export/rygel-media-export-harvester.vala b/src/plugins/media-export/rygel-media-export-harvester.vala index 4a2c2c0..1861708 100644 --- a/src/plugins/media-export/rygel-media-export-harvester.vala +++ b/src/plugins/media-export/rygel-media-export-harvester.vala @@ -284,7 +284,11 @@ public class Rygel.MediaExport.Harvester : GLib.Object { } } - private void on_extracted_cb (File file, Gst.TagList tag_list) { + private void on_extracted_cb (File file, + GUPnP.DLNAInformation dlna, + string mime, + uint64 size, + uint64 mtime) { if (this.cancellable.is_cancelled ()) { harvested (this.origin); } @@ -296,10 +300,13 @@ public class Rygel.MediaExport.Harvester : GLib.Object { return; } if (file == entry) { - var item = MediaExportItem.create_from_taglist ( - this.containers.peek_head (), - file, - tag_list); + var item = MediaExportItem.create_from_info ( + this.containers.peek_head (), + file, + dlna, + mime, + size, + mtime); if (item != null) { item.parent_ref = this.containers.peek_head (); try { diff --git a/src/plugins/media-export/rygel-media-export-item.vala b/src/plugins/media-export/rygel-media-export-item.vala index 6f5163b..5ec1ce1 100644 --- a/src/plugins/media-export/rygel-media-export-item.vala +++ b/src/plugins/media-export/rygel-media-export-item.vala @@ -28,153 +28,196 @@ using Gst; * Represents MediaExport item. */ public class Rygel.MediaExport.MediaExportItem : Rygel.MediaItem { - private const string TAG_WIDTH = MetadataExtractor.TAG_RYGEL_WIDTH; - private const string TAG_HEIGHT = MetadataExtractor.TAG_RYGEL_HEIGHT; - private const string - TAG_DLNA_PROFILE = MetadataExtractor.TAG_RYGEL_DLNA_PROFILE; - - public static MediaExportItem? create_from_taglist (MediaContainer parent, - File file, - Gst.TagList tag_list) { + public static MediaExportItem? create_from_info ( + MediaContainer parent, + File file, + GUPnP.DLNAInformation dlna_info, + string mime, + uint64 size, + uint64 mtime) { string id = Checksum.compute_for_string (ChecksumType.MD5, file.get_uri ()); - int width = -1; - int height = -1; - string class_guessed = null; - - if (tag_list != null) { - string codec; - - if (!tag_list.get_string (TAG_VIDEO_CODEC, out codec)) { - if (!tag_list.get_string (TAG_AUDIO_CODEC, out codec)) { - if (tag_list.get_int (TAG_WIDTH, out width) || - tag_list.get_int (TAG_HEIGHT, out height)) { - class_guessed = Rygel.MediaItem.PHOTO_CLASS; - } else { - // if it has width and height and a duration, assume - // it is a video (to capture the MPEG TS without audio - // case) - uint64 duration; - if (tag_list.get_uint64 (TAG_DURATION, - out duration)) { - class_guessed = Rygel.MediaItem.VIDEO_CLASS; - } else { - string content_type; - tag_list.get_string (MetadataExtractor.TAG_RYGEL_MIME, - out content_type); - debug (_("File '%s' is of unknown format/type."), - file.get_uri ()); - debug (_("Trying to guess from content type %s"), - content_type); - if (content_type.has_prefix ("video/")) { - class_guessed = Rygel.MediaItem.VIDEO_CLASS; - } else if (content_type.has_prefix ("audio/")) { - class_guessed = Rygel.MediaItem.AUDIO_CLASS; - } else if (content_type.has_prefix ("image/")) { - class_guessed = Rygel.MediaItem.PHOTO_CLASS; - } - - if (class_guessed == null) { - class_guessed = Rygel.MediaItem.AUDIO_CLASS; - warning (_("Failed to detect UPnP class for '%s', assuming '%s'"), - file.get_uri (), - class_guessed); - } - } - } - } else { - // MPEG TS streams seem to miss VIDEO_CODEC; so if we have - // an AUDIO_CODEC and width or height, assume video as - // well - if (tag_list.get_int (TAG_WIDTH, out width) || - tag_list.get_int (TAG_HEIGHT, out height)) { - class_guessed = Rygel.MediaItem.VIDEO_CLASS; - } else { - class_guessed = Rygel.MediaItem.AUDIO_CLASS; - } - } + unowned Gst.StreamInformation audio = null; + unowned Gst.StreamInformation video = null; + + foreach (unowned Gst.StreamInformation stream_info in + dlna_info.info.stream_list) { + if (audio == null && + stream_info.streamtype == Gst.StreamType.AUDIO) { + audio = stream_info; + } else if (video == null && + (stream_info.streamtype == Gst.StreamType.VIDEO || + stream_info.streamtype == Gst.StreamType.IMAGE)) { + video = stream_info; + } + } + + if (video != null) { + if (audio == null && video.streamtype == Gst.StreamType.IMAGE) { + return new MediaExportItem.photo ( + parent, + id, + file, + dlna_info, + (Gst.StreamVideoInformation) video, + mime, + size, + mtime); } else { - class_guessed = Rygel.MediaItem.VIDEO_CLASS; + return new MediaExportItem.video ( + parent, + id, + file, + dlna_info, + (Gst.StreamVideoInformation) video, + (Gst.StreamAudioInformation) audio, + mime, + size, + mtime); } + } else if (audio != null) { + return new MediaExportItem.audio ( + parent, + id, + file, + dlna_info, + (Gst.StreamAudioInformation) audio, + mime, + size, + mtime); } else { - // throw error. Taglist can't be empty - warning (_("Got empty taglist for file %s"), file.get_uri ()); - return null; } + } + + private MediaExportItem.video (MediaContainer parent, + string id, + File file, + GUPnP.DLNAInformation dlna_info, + Gst.StreamVideoInformation? video, + Gst.StreamAudioInformation? audio, + string mime, + uint64 size, + uint64 mtime) { + this (parent, + id, + file, + dlna_info, + mime, + size, + mtime, + MediaItem.VIDEO_CLASS); + + this.width = (int) video.width; + this.height = (int) video.height; + this.color_depth = (int) video.depth; + + if (video.tags != null) { + uint tmp; + + video.tags.get_uint (TAG_BITRATE, out tmp); + this.bitrate = (int) tmp / 8; + } - return new MediaExportItem (parent, - id, - file, - tag_list, - class_guessed); + this.n_audio_channels = (int) audio.channels; + this.sample_freq = (int) audio.sample_rate; } - private MediaExportItem (MediaContainer parent, - string id, - File file, - Gst.TagList tag_list, - string upnp_class) { - string title = null; - if (upnp_class == Rygel.MediaItem.AUDIO_CLASS || - upnp_class == Rygel.MediaItem.MUSIC_CLASS) { + private MediaExportItem.photo (MediaContainer parent, + string id, + File file, + GUPnP.DLNAInformation dlna_info, + Gst.StreamVideoInformation? video, + string mime, + uint64 size, + uint64 mtime) { + this (parent, + id, + file, + dlna_info, + mime, + size, + mtime, + MediaItem.PHOTO_CLASS); + + this.width = (int) video.width; + this.height = (int) video.height; + this.color_depth = (int) video.depth; + } - if (!tag_list.get_string (TAG_TITLE, out title)) { - title = file.get_basename (); - } + private MediaExportItem.audio (MediaContainer parent, + string id, + File file, + GUPnP.DLNAInformation dlna_info, + Gst.StreamAudioInformation? audio, + string mime, + uint64 size, + uint64 mtime) { + this (parent, + id, + file, + dlna_info, + mime, + size, + mtime, + MediaItem.MUSIC_CLASS); + + this.n_audio_channels = (int) audio.channels; + this.sample_freq = (int) audio.sample_rate; + } - } else { + private MediaExportItem (MediaContainer parent, + string id, + File file, + GUPnP.DLNAInformation dlna_info, + string mime, + uint64 size, + uint64 mtime, + string upnp_class) { + string title = null; + + if (dlna_info.info.tags == null || + !dlna_info.info.tags.get_string (TAG_TITLE, out title)) { title = file.get_basename (); } - base (id, parent, title, upnp_class); - tag_list.get_int (TAG_WIDTH, out this.width); - tag_list.get_int (TAG_HEIGHT, out this.height); - tag_list.get_int (MetadataExtractor.TAG_RYGEL_DEPTH, - out this.color_depth); - uint64 duration; - tag_list.get_uint64 (TAG_DURATION, out duration); - this.duration = (duration == -1) ? -1 : (long) (duration / 1000000000); + base (id, parent, title, upnp_class); - tag_list.get_int (MetadataExtractor.TAG_RYGEL_CHANNELS, - out this.n_audio_channels); + if (dlna_info.info.duration > -1) { + this.duration = -1; + } else { + this.duration = dlna_info.info.duration / Gst.SECOND; + } - tag_list.get_string (TAG_ARTIST, out this.author); - tag_list.get_string (TAG_ALBUM, out this.album); + if (dlna_info.info.tags != null) { + dlna_info.info.tags.get_string (TAG_ARTIST, out this.author); + dlna_info.info.tags.get_string (TAG_ALBUM, out this.album); - uint tmp; - tag_list.get_uint (TAG_TRACK_NUMBER, out tmp); - this.track_number = (int) tmp; - tag_list.get_uint (TAG_BITRATE, out tmp); - this.bitrate = (int) tmp / 8; - tag_list.get_int (MetadataExtractor.TAG_RYGEL_RATE, - out this.sample_freq); + uint tmp; + dlna_info.info.tags.get_uint (TAG_TRACK_NUMBER, out tmp); + this.track_number = (int) tmp; + GLib.Date? date; + if (dlna_info.info.tags.get_date (TAG_DATE, out date)) { + char[] datestr = new char[30]; + date.strftime (datestr, "%F"); + this.date = (string) datestr; + } else { + TimeVal tv = { (long) mtime, 0 }; + this.date = tv.to_iso8601 (); + } + } - int64 size; - tag_list.get_int64 (MetadataExtractor.TAG_RYGEL_SIZE, - out size); this.size = (long) size; - - uint64 mtime; - tag_list.get_uint64 (MetadataExtractor.TAG_RYGEL_MTIME, - out mtime); this.modified = (int64) mtime; - GLib.Date? date; - if (tag_list.get_date (TAG_DATE, out date)) { - char[] datestr = new char[30]; - date.strftime (datestr, "%F"); - this.date = (string) datestr; + if (dlna_info.name != null) { + this.dlna_profile = dlna_info.name; + this.mime_type = dlna_info.mime; } else { - TimeVal tv = { (long) mtime, 0 }; - this.date = tv.to_iso8601 (); + this.mime_type = mime; } - tag_list.get_string (TAG_DLNA_PROFILE, out this.dlna_profile); - tag_list.get_string (MetadataExtractor.TAG_RYGEL_MIME, - out this.mime_type); - this.add_uri (file.get_uri (), null); } } diff --git a/src/plugins/media-export/rygel-media-export-metadata-extractor.vala b/src/plugins/media-export/rygel-media-export-metadata-extractor.vala index 0263f73..02ae121 100644 --- a/src/plugins/media-export/rygel-media-export-metadata-extractor.vala +++ b/src/plugins/media-export/rygel-media-export-metadata-extractor.vala @@ -33,18 +33,12 @@ using GUPnP; * metadata_available for each key/value pair extracted. */ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { - public const string TAG_RYGEL_SIZE = "rygel-size"; - public const string TAG_RYGEL_MIME = "rygel-mime"; - public const string TAG_RYGEL_CHANNELS = "rygel-channels"; - public const string TAG_RYGEL_RATE = "rygel-rate"; - public const string TAG_RYGEL_WIDTH = "rygel-width"; - public const string TAG_RYGEL_HEIGHT = "rygel-height"; - public const string TAG_RYGEL_DEPTH = "rygel-depth"; - public const string TAG_RYGEL_MTIME = "rygel-mtime"; - public const string TAG_RYGEL_DLNA_PROFILE = "rygel-dlna-profile"; - /* Signals */ - public signal void extraction_done (File file, Gst.TagList tag_list); + public signal void extraction_done (File file, + GUPnP.DLNAInformation info, + string mime, + uint64 size, + uint64 mtime); /** * Signalize that an error occured during metadata extraction @@ -60,30 +54,11 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { private HashMap file_hash; private uint64 timeout = 10; /* seconds */ - private static void register_custom_tag (string tag, Type type) { - Gst.tag_register (tag, - TagFlag.META, - type, - tag, - "", - Gst.tag_merge_use_first); - } - public static MetadataExtractor? create () { return new MetadataExtractor (); } public MetadataExtractor () { - this.register_custom_tag (TAG_RYGEL_SIZE, 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.register_custom_tag (TAG_RYGEL_DLNA_PROFILE, typeof (string)); - this.file_hash = new HashMap (); this.discoverer = new GUPnP.DLNADiscoverer ((ClockTime) @@ -101,7 +76,6 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { assert (this.file_hash.has_key (dlna.info.uri)); File file = this.file_hash.get (dlna.info.uri); - TagList tag_list = new TagList (); this.file_hash.unset (dlna.info.uri); @@ -116,16 +90,11 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { } try { - this.extract_mime_and_size (file, tag_list); - this.extract_duration (dlna.info, tag_list); - this.extract_stream_info (dlna.info, tag_list); - if (dlna.name != null) { - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_DLNA_PROFILE, - dlna.name); - tag_list.add (TagMergeMode.REPLACE, TAG_RYGEL_MIME, dlna.mime); - } - this.extraction_done (file, tag_list); + uint64 size, mtime; + string mime; + + this.extract_file_info (file, out mime, out size, out mtime); + this.extraction_done (file, dlna, mime, size, mtime); } catch (Error e) { debug (_("Failed to extract metadata from %s: %s"), dlna.info.uri, @@ -139,8 +108,10 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { this.discoverer.discover_uri (uri); } - private void extract_mime_and_size (File file, - TagList tag_list) throws Error { + private void extract_file_info (File file, + out string mime, + out uint64 size, + out uint64 mtime) throws Error { FileInfo file_info; try { @@ -161,64 +132,8 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object { } string content_type = file_info.get_content_type (); - string mime = g_content_type_get_mime_type (content_type); - - if (mime != null) { - /* add custom mime tag to tag list */ - tag_list.add (TagMergeMode.REPLACE, TAG_RYGEL_MIME, mime); - } - - var size = file_info.get_size (); - tag_list.add (TagMergeMode.REPLACE, TAG_RYGEL_SIZE, size); - - var mtime = file_info.get_attribute_uint64 ( - FILE_ATTRIBUTE_TIME_MODIFIED); - tag_list.add (TagMergeMode.REPLACE, TAG_RYGEL_MTIME, mtime); - } - - private void extract_duration (Gst.DiscovererInformation info, - TagList tag_list) { - tag_list.add (TagMergeMode.REPLACE, - TAG_DURATION, - info.duration); - } - - private void extract_stream_info (Gst.DiscovererInformation info, - TagList tag_list) { - foreach (unowned Gst.StreamInformation i in info.stream_list) { - if (i.streamtype == Gst.StreamType.VIDEO) { - extract_video_info ((Gst.StreamVideoInformation) i, tag_list); - } else if (i.streamtype == Gst.StreamType.AUDIO) { - extract_audio_info ((Gst.StreamAudioInformation) i, tag_list); - } - } - } - - private void extract_audio_info (Gst.StreamAudioInformation info, - TagList tag_list) { - if (info.sample_rate != 0) - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_RATE, - info.sample_rate); - if (info.channels != 0) - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_CHANNELS, - info.channels); - } - - private void extract_video_info (Gst.StreamVideoInformation info, - TagList tag_list) { - if (info.depth != 0) - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_DEPTH, - info.depth); - if (info.width != 0) - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_WIDTH, - info.width); - if (info.height != 0) - tag_list.add (TagMergeMode.REPLACE, - TAG_RYGEL_HEIGHT, - info.height); + mime = g_content_type_get_mime_type (content_type); + size = file_info.get_size (); + mtime = file_info.get_attribute_uint64 (FILE_ATTRIBUTE_TIME_MODIFIED); } } -- 2.7.4