diff --git a/samples/Makefile.am b/samples/Makefile.am index e62ccbb1d3..e5db3c8d6c 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -1,4 +1,4 @@ -TARGETS = playback.exe video-overlay.exe basic-tutorial-1.exe basic-tutorial-2.exe basic-tutorial-3.exe basic-tutorial-4.exe basic-tutorial-5.exe basic-tutorial-6.exe basic-tutorial-7.exe basic-tutorial-8.exe basic-tutorial-9.exe basic-tutorial-12.exe basic-tutorial-13.exe playback-tutorial-1.exe playback-tutorial-2.exe playback-tutorial-3.exe +TARGETS = playback.exe video-overlay.exe basic-tutorial-1.exe basic-tutorial-2.exe basic-tutorial-3.exe basic-tutorial-4.exe basic-tutorial-5.exe basic-tutorial-6.exe basic-tutorial-7.exe basic-tutorial-8.exe basic-tutorial-9.exe basic-tutorial-12.exe basic-tutorial-13.exe playback-tutorial-1.exe playback-tutorial-2.exe playback-tutorial-3.exe playback-tutorial-4.exe DEBUGS = $(addsuffix .mdb, $(TARGETS)) assemblies = \ @@ -57,6 +57,9 @@ playback-tutorial-2.exe: $(srcdir)/PlaybackTutorial2.cs $(assemblies) playback-tutorial-3.exe: $(srcdir)/PlaybackTutorial3.cs $(assemblies) $(CSC) $(CSFLAGS) -out:playback-tutorial-3.exe $(references) $(GLIB_SHARP_LIBS) $(srcdir)/PlaybackTutorial3.cs +playback-tutorial-4.exe: $(srcdir)/PlaybackTutorial4.cs $(assemblies) + $(CSC) $(CSFLAGS) -out:playback-tutorial-4.exe $(references) $(GLIB_SHARP_LIBS) $(srcdir)/PlaybackTutorial4.cs + EXTRA_DIST = \ Playback.cs \ VideoOverlay.cs \ @@ -73,4 +76,5 @@ EXTRA_DIST = \ BasicTutorial13.cs \ PlaybackTutorial1.cs \ PlaybackTutorial2.cs \ - PlaybackTutorial3.cs + PlaybackTutorial3.cs \ + PlaybackTutorial4.cs diff --git a/samples/PlaybackTutorial4.cs b/samples/PlaybackTutorial4.cs new file mode 100644 index 0000000000..885543a4b8 --- /dev/null +++ b/samples/PlaybackTutorial4.cs @@ -0,0 +1,147 @@ +// Authors +// Copyright (C) 2014 Stephan Sundermann + +using System; +using Gst; +using System.Runtime.InteropServices; +using System.Text; + +namespace GstreamerSharp +{ + class Playback + { + const int GraphLength = 78; + static uint PlayFlagDownload = (1 << 7); // Enable progressive download (on selected formats) + + static bool IsLive; + static Element Pipeline; + static GLib.MainLoop MainLoop; + static int BufferingLevel; + + static void GotLocation (object sender, GLib.SignalArgs args) { + var propObject = (Gst.Object)args.Args [0]; + var location = (string) propObject["temp-location"]; + Console.WriteLine ("Temporary file: {0}", location); + // Uncomment this line to keep the temporary file after the program exits + // g_object_set (G_OBJECT (prop_object), "temp-remove", FALSE, NULL); + } + + public static void Main (string[] args) + { + // Initialize GStreamer + Application.Init (ref args); + BufferingLevel = 100; + + // Build the pipeline + Pipeline = Parse.Launch ("playbin uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm"); + var bus = Pipeline.Bus; + + // Set the download flag + var flags = (uint)Pipeline ["flags"]; + flags |= PlayFlagDownload; + Pipeline ["flags"] = flags; + + // Uncomment this line to limit the amount of downloaded data + // g_object_set (pipeline, "ring-buffer-max-size", (guint64)4000000, NULL); + + // Start playing + var ret = Pipeline.SetState (State.Playing); + if (ret == StateChangeReturn.Failure) { + Console.WriteLine ("Unable to set the pipeline to the playing state."); + return; + } else if (ret == StateChangeReturn.NoPreroll) { + IsLive = true; + } + + MainLoop = new GLib.MainLoop (); + + bus.AddSignalWatch (); + bus.Message += HandleMessage; + Pipeline.Connect ("deep-notify::temp-location", GotLocation); + + // Register a function that GLib will call every second + GLib.Timeout.AddSeconds (1, RefreshUI); + + MainLoop.Run (); + + // Free resources + Pipeline.SetState (State.Null); + } + + static void HandleMessage (object o, MessageArgs args) + { + var msg = args.Message; + switch (msg.Type) { + case MessageType.Error: { + GLib.GException err; + string debug; + + msg.ParseError (out err, out debug); + Console.WriteLine ("Error: {0}", err.Message); + + Pipeline.SetState (State.Ready); + MainLoop.Quit (); + break; + } + case MessageType.Eos: + // end-of-stream + Pipeline.SetState (State.Ready); + MainLoop.Quit (); + break; + case MessageType.Buffering: { + int percent = 0; + + // If the stream is live, we do not care about buffering. + if (IsLive) break; + + percent = msg.ParseBuffering (); + // Wait until buffering is complete before start/resume playing + if (percent < 100) + Pipeline.SetState (State.Paused); + else + Pipeline.SetState (State.Playing); + break; + } + case MessageType.ClockLost: + // Get a new clock + Pipeline.SetState (State.Paused); + Pipeline.SetState (State.Playing); + break; + default: + // Unhandled message + break; + } + } + + static bool RefreshUI () { + var query = new Query (Format.Percent); + if (Pipeline.Query (query)) { + var graph = new StringBuilder (GraphLength); + long position = 0, duration = 0; + + var nRanges = query.NBufferingRanges; + for (uint range = 0; range < nRanges; range++) { + long start, stop; + query.ParseNthBufferingRange (range, out start, out stop); + start = start * GraphLength / (stop - start); + stop = stop * GraphLength / (stop - start); + for (int i = (int)start; i < stop; i++) + graph.Insert (i, '-'); + } + if (Pipeline.QueryPosition (Format.Time, out position) && position >= 0 + && Pipeline.QueryDuration (Format.Time, out duration) && duration >= 0) { + var i = (int)(GraphLength * (double)position / (double)(duration + 1)); + graph [i] = BufferingLevel < 100 ? 'X' : '>'; + } + Console.WriteLine ("[{0}]", graph); + if (BufferingLevel < 100) { + Console.WriteLine (" Buffering: {0}", BufferingLevel); + } else { + Console.WriteLine (" "); + } + Console.WriteLine (); + } + return true; + } + } +} \ No newline at end of file