// Authors // Copyright (C) 2014 Stephan Sundermann using System; using Gst; using System.Runtime.InteropServices; namespace GstreamerSharp { class Playback { // Functions below print the capabilities in a human-friendly format static void PrintCaps (Caps caps, string pfx) { if (caps == null) return; if (caps.IsAny) { Console.WriteLine ("{0}ANY", pfx); return; } if (caps.IsEmpty) { Console.WriteLine ("{0}EMPTY", pfx); return; } for (uint i = 0; i < caps.Size; i++) { var structure = caps.GetStructure (i); Console.WriteLine ("{0}{1}", pfx, structure.Name); structure.Foreach ((field_id, value) => { var ptr = g_quark_to_string (field_id); var quark = GLib.Marshaller.Utf8PtrToString (ptr); Console.WriteLine ("{0} {1}: {2}", pfx, quark, value.Val); return true; }); } } // Prints information about a Pad Template, including its Capabilities*/ static void PrintPadTemplateInformation (ElementFactory factory) { Console.WriteLine ("Pad Templates for {0}:", factory.Name); if (factory.NumPadTemplates == 0) { Console.WriteLine (" none"); return; } var pads = factory.StaticPadTemplates; foreach (var p in pads) { var pad = (StaticPadTemplate) p; if (pad.Direction == PadDirection.Src) Console.WriteLine (" SRC template: '{0}'", pad.NameTemplate); else if (pad.Direction == PadDirection.Sink) Console.WriteLine (" SINK template: '{0}'", pad.NameTemplate); else Console.WriteLine (" UNKNOWN!!! template: '{0}'", pad.NameTemplate); if (pad.Presence == PadPresence.Always) Console.WriteLine (" Availability: Always"); else if (pad.Presence == PadPresence.Sometimes) Console.WriteLine (" Availability: Sometimes"); else if (pad.Presence == PadPresence.Request) { Console.WriteLine (" Availability: On request"); } else Console.WriteLine (" Availability: UNKNOWN!!!"); if (pad.StaticCaps.String != null) { Console.WriteLine (" Capabilities:"); PrintCaps (pad.StaticCaps.Get (), " "); } Console.WriteLine (); } } // Shows the CURRENT capabilities of the requested pad in the given element */ static void PrintPadCapabilities (Element element, string padName) { // Retrieve pad var pad = element.GetStaticPad (padName); if (pad == null) { Console.WriteLine ("Could not retrieve pad '{0}'", padName); return; } // Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) var caps = pad.CurrentCaps; if (caps == null) caps = pad.Caps; /* Print and free */ Console.WriteLine ("Caps for the {0} pad:", padName); PrintCaps (caps, " "); } public static void Main (string[] args) { // Initialize Gstreamer Gst.Application.Init(ref args); // Create the element factories var sourceFactory = ElementFactory.Find ("audiotestsrc"); var sinkFactory = ElementFactory.Find ("autoaudiosink"); if (sourceFactory == null || sinkFactory == null) { Console.WriteLine ("Not all element factories could be created."); return; } // Print information about the pad templates of these factories PrintPadTemplateInformation (sourceFactory); PrintPadTemplateInformation (sinkFactory); // Ask the factories to instantiate actual elements var source = sourceFactory.Create ("source"); var sink = sinkFactory.Create ("sink"); // Create the empty pipeline var pipeline = new Pipeline ("test-pipeline"); if (pipeline == null || source == null || sink == null) { Console.WriteLine ("Not all elements could be created."); return; } // Build the pipeline pipeline.Add (source, sink); if (!source.Link (sink)) { Console.WriteLine ("Elements could not be linked."); return; } // Print initial negotiated caps (in NULL state) Console.WriteLine ("In NULL state:"); PrintPadCapabilities (sink, "sink"); // Start playing var ret = pipeline.SetState (State.Playing); if (ret == StateChangeReturn.Failure) { Console.WriteLine ("Unable to set the pipeline to the playing state (check the bus for error messages)."); } // Wait until error, EOS or State Change var bus = pipeline.Bus; var terminate = false; do { var msg = bus.TimedPopFiltered (Constants.CLOCK_TIME_NONE, MessageType.Error | MessageType.Eos | MessageType.StateChanged); // Parse message if (msg != null) { switch (msg.Type) { case MessageType.Error: string debug; GLib.GException exc; msg.ParseError (out exc, out debug); Console.WriteLine ("Error received from element {0}: {1}", msg.Src.Name, exc.Message); Console.WriteLine ("Debugging information: {0}", debug != null ? debug : "none"); terminate = true; break; case MessageType.Eos: Console.WriteLine ("End-Of-Stream reached.\n"); terminate = true; break; case MessageType.StateChanged: // We are only interested in state-changed messages from the pipeline if (msg.Src == pipeline) { State oldState, newState, pendingState; msg.ParseStateChanged (out oldState, out newState, out pendingState); Console.WriteLine ("Pipeline state changed from {0} to {1}:", Element.StateGetName (oldState), Element.StateGetName (newState)); // Print the current capabilities of the sink element PrintPadCapabilities (sink, "sink"); } break; default: // We should not reach here because we only asked for ERRORs, EOS and STATE_CHANGED Console.WriteLine ("Unexpected message received."); break; } } } while (!terminate); // Free resources pipeline.SetState (State.Null); } [DllImport ("glib-2.0.dll")] static extern IntPtr g_quark_to_string (uint quark); } }