// Authors // Copyright (C) 2014 Stephan Sundermann using System; using Gst; using Gst.PbUtils; using System.Runtime.InteropServices; namespace GstreamerSharp { class Playback { static Discoverer Discoverer; static GLib.MainLoop MainLoop; // Print a tag in a human-readable format (name: value) static void PrintTagForeach (TagList tags, string tag, int depth) { var val = GLib.Value.Empty; TagList.CopyValue (ref val, tags, tag); string str; if (val.Val is string) str = (string)val.Val; else str = Value.Serialize (val); Console.WriteLine ("{0}{1}: {2}", new string(' ', 2 * depth), Tag.GetNick (tag), str); } // Print information regarding a stream static void PrintStreamInfo (DiscovererStreamInfo info, int depth) { var caps = info.Caps; string desc = null; if (caps != null) { if (caps.IsFixed) desc = Gst.PbUtils.Global.PbUtilsGetCodecDescription (caps); else desc = caps.ToString (); } Console.WriteLine ("{0}{1}: {2}", new string (' ', 2 * depth), info.StreamTypeNick, (desc != null ? desc : "")); var tags = info.Tags; if (tags != null) { Console.WriteLine ("{0}Tags:", new string (' ', 2 * (depth + 1))); tags.Foreach ((TagForeachFunc)delegate (TagList list, string tag) { PrintTagForeach (list, tag, depth + 2); }); } } // Print information regarding a stream and its substreams, if any static void PrintTopology (DiscovererStreamInfo info, int depth) { if (info == null) return; PrintStreamInfo (info, depth); var next = info.Next; if (next != null) { PrintTopology (next, depth + 1); } else if (info is DiscovererContainerInfo) { var streams = ((DiscovererContainerInfo)info).Streams; foreach (var stream in streams) { PrintTopology (stream, depth + 1); } } } //This function is called every time the discoverer has information regarding one of the URIs we provided. static void HandleDiscovered (object disc, DiscoveredArgs args) { var info = args.Info; var uri = info.Uri; var result = info.Result; var discoverer = (Discoverer)disc; switch (result) { case DiscovererResult.UriInvalid: Console.WriteLine ("Invalid URI '{0}'", uri); break; case DiscovererResult.Error: var err = new GLib.GException (args.Error); Console.WriteLine ("Discoverer error: {0}", err.Message); break; case DiscovererResult.Timeout: Console.WriteLine ("Timeout"); break; case DiscovererResult.Busy: Console.WriteLine ("Busy"); break; case DiscovererResult.MissingPlugins:{ var s = info.Misc; if (s != null) { Console.WriteLine ("Missing plugins: {0}", s); } break; } case DiscovererResult.Ok: Console.WriteLine ("Discovered '{0}'", uri); break; } if (result != DiscovererResult.Ok) { Console.WriteLine ("This URI cannot be played"); return; } // If we got no error, show the retrieved information Console.WriteLine ("\nDuration: {0}", new TimeSpan((long)info.Duration)); var tags = info.Tags; if (tags != null) { Console.WriteLine ("Tags:"); tags.Foreach ((TagForeachFunc)delegate (TagList list, string tag) { PrintTagForeach (list, tag, 1); }); } Console.WriteLine ("Seekable: {0}", (info.Seekable ? "yes" : "no")); Console.WriteLine (); var sinfo = info.StreamInfo; if (sinfo == null) return; Console.WriteLine ("Stream information:"); PrintTopology (sinfo, 1); Console.WriteLine (); } public static void Main (string[] args) { var uri = "http://download.blender.org/durian/trailer/sintel_trailer-1080p.mp4"; // if a URI was provided, use it instead of the default one if (args.Length > 1) { uri = args[0]; } // Initialize GStreamer Gst.Application.Init (ref args); Console.WriteLine ("Discovering '{0}'", uri); // Instantiate the Discoverer Discoverer = new Discoverer (5L * Gst.Constants.SECOND); // Connect to the interesting signals Discoverer.Discovered += HandleDiscovered; Discoverer.Finished += (sender, e) => { Console.WriteLine ("Finished discovering"); MainLoop.Quit (); }; // Start the discoverer process (nothing to do yet) Discoverer.Start (); // Add a request to process asynchronously the URI passed through the command line if (!Discoverer.DiscoverUriAsync (uri)) { Console.WriteLine ("Failed to start discovering URI '{0}'", uri); return; } // Create a GLib Main Loop and set it to run, so we can wait for the signals MainLoop = new GLib.MainLoop (); MainLoop.Run (); // Stop the discoverer process Discoverer.Stop (); } } }