// Authors // Copyright (C) 2014 Stephan Sundermann using System; using Gst; namespace GstreamerSharp { class Playback { static Element playbin; static bool playing; static bool terminate; static bool seekEnabled; static bool seekDone; static long duration; public static void Main (string[] args) { // Initialize Gstreamer Application.Init(ref args); // Create the elements playbin = ElementFactory.Make ("playbin", "playbin"); if (playbin == null) { Console.WriteLine ("Not all elements could be created"); return; } // Set the URI to play. playbin ["uri"] = "http://download.blender.org/durian/trailer/sintel_trailer-1080p.mp4"; // Start playing var ret = playbin.SetState (State.Playing); if (ret == StateChangeReturn.Failure) { Console.WriteLine ("Unable to set the pipeline to the playing state."); return; } // Listen to the bus var bus = playbin.Bus; do { var msg = bus.TimedPopFiltered (100 * Constants.MSECOND, MessageType.StateChanged | MessageType.Error | MessageType.DurationChanged); // Parse message if (msg != null) { HandleMessage (msg); } else { // We got no message, this means the timeout expired if (playing) { var fmt = Format.Time; var current = -1L; // Query the current position of the stream if (!playbin.QueryPosition (fmt, out current)) { Console.WriteLine ("Could not query current position."); } // if we didn't know it yet, query the stream position if (duration <= 0) { if (!playbin.QueryDuration (fmt, out duration)) { Console.WriteLine ("Could not query current duration."); } } // Print current position and total duration Console.Write("Position {0} / {1}\r", new TimeSpan (current), new TimeSpan (duration)); if (seekEnabled && !seekDone && current > 10L * Constants.SECOND) { Console.WriteLine ("\nRead 10s, performing seek..."); playbin.SeekSimple (fmt, SeekFlags.KeyUnit | SeekFlags.Flush, 30L * Constants.SECOND); seekDone = true; } } } } while (!terminate); } private static void HandleMessage (Message msg) { switch (msg.Type) { case MessageType.Error: string debug; GLib.GException exc; msg.ParseError (out exc, out debug); Console.WriteLine (string.Format ("Error received from element {0}: {1}", msg.Src.Name, exc.Message)); Console.WriteLine ("Debugging information: {0}", debug); terminate = true; break; case MessageType.Eos: Console.WriteLine("End-Of-Stream reached."); terminate = true; break; case MessageType.DurationChanged: // The duration has changed, mark the current one as invalid duration = -1; break; case MessageType.StateChanged: // We are only interested in state-changed messages from the pipeline if (msg.Src == playbin) { 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)); // Remember wheather we are in the PLAYING state playing = newState == State.Playing; if (playing) { // We have just moved to PLAYING. Check if seeking is possible var query = Query.NewSeeking (Format.Time); long start, end; Format fmt = Format.Time; if (playbin.Query (query)) { query.ParseSeeking (out fmt, out seekEnabled, out start, out end); if (seekEnabled) { Console.WriteLine ("Seeking is ENABLED from {0} to {1}", new TimeSpan(start), new TimeSpan(end)); } else { Console.WriteLine ("Seeking DISABLED for this stream."); } } else { Console.WriteLine ("Seeking query failed."); } } } break; default: // We should not reach here Console.WriteLine ("Unexpected message received."); break; } } } }