summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Sundermann <stephansundermann@gmail.com>2013-10-21 19:10:04 +0200
committerStephan Sundermann <stephansundermann@gmail.com>2013-12-21 16:52:27 +0100
commitdf285b417a2daa4e2ea6fa5b51725b4a3c56f7ab (patch)
treedb3daf723979f350e222100cc0788c3940c7a53a
parent5ac90c0cedd3f69db3fed41ee5cdeb59dd58674b (diff)
Samples: Ported overlay sample from 0.10
Hangs on shutdown when playing a video for some reason
-rw-r--r--samples/VideoOverlay.cs274
1 files changed, 274 insertions, 0 deletions
diff --git a/samples/VideoOverlay.cs b/samples/VideoOverlay.cs
new file mode 100644
index 0000000..e17fd20
--- /dev/null
+++ b/samples/VideoOverlay.cs
@@ -0,0 +1,274 @@
+// Authors
+// Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
+// Copyright (C) 2010 Andoni Morales <ylatuya@gmail.com>
+// Copyright (C) 2013 Stephan Sundermann <stephansundermann@gmail.com>
+
+using System;
+using System;
+using System.Runtime.InteropServices;
+
+using Gtk;
+using Gst;
+using Gst.Video;
+using Gst.Base;
+
+namespace Gstreameroverlay
+{
+ public class MainWindow : Gtk.Window {
+ DrawingArea _da;
+ ulong _xWindowId;
+ Element _playbin;
+ HScale _scale;
+ Label _lbl;
+ bool _updatingScale;
+ bool _pipelineOK = false;
+
+ public static void Main (string[] args) {
+ if (System.Environment.OSVersion.Platform == PlatformID.Unix)
+ XInitThreads ();
+
+ Gtk.Application.Init ();
+ Gst.Application.Init ();
+ MainWindow window = new MainWindow ();
+ window.ShowAll ();
+
+ switch (System.Environment.OSVersion.Platform) {
+ case PlatformID.Unix:
+ window._xWindowId = gdk_x11_window_get_xid (window._da.GdkWindow.Handle);
+ break;
+ case PlatformID.Win32NT:
+ case PlatformID.Win32S:
+ case PlatformID.Win32Windows:
+ case PlatformID.WinCE:
+ window._xWindowId = (ulong) gdk_win32_drawable_get_handle (window._da.GdkWindow.Handle);
+ break;
+ }
+
+ Gtk.Application.Run ();
+ }
+
+ public MainWindow ()
+ : base ("Overlaytest") {
+ VBox vBox = new VBox ();
+
+ _da = new DrawingArea ();
+ _da.ModifyBg (Gtk.StateType.Normal, new Gdk.Color (0, 0, 0));
+ _da.SetSizeRequest (400, 300);
+ _da.DoubleBuffered = false;
+ vBox.PackStart (_da, false, false, 0);
+
+ _scale = new HScale (0, 1, 0.01);
+ _scale.DrawValue = false;
+ _scale.ValueChanged += ScaleValueChanged;
+ vBox.PackStart (_scale, false, false, 0);
+
+ HBox hBox = new HBox ();
+
+ Button btnOpen = new Button ();
+ btnOpen.Label = "Open";
+ btnOpen.Clicked += ButtonOpenClicked;
+
+ hBox.PackStart (btnOpen, false, false, 0);
+
+ Button btnPlay = new Button ();
+ btnPlay.Label = "Play";
+ btnPlay.Clicked += ButtonPlayClicked;
+
+ hBox.PackStart (btnPlay, false, false, 0);
+
+ Button btnPause = new Button ();
+ btnPause.Label = "Pause";
+ btnPause.Clicked += ButtonPauseClicked;
+
+ hBox.PackStart (btnPause, false, false, 0);
+
+ _lbl = new Label ();
+ _lbl.Text = "00:00 / 00:00";
+
+ hBox.PackEnd (_lbl, false, false, 0);
+
+ vBox.PackStart (hBox, false, false, 3);
+
+ Add (vBox);
+
+ WindowPosition = Gtk.WindowPosition.Center;
+ DeleteEvent += OnDeleteEvent;
+
+ GLib.Timeout.Add (1000, new GLib.TimeoutHandler (UpdatePos));
+ }
+
+ void OnDeleteEvent (object sender, DeleteEventArgs args) {
+ Gtk.Application.Quit ();
+
+
+ if (_playbin != null) {
+ _playbin.SetState (Gst.State.Null);
+ _playbin.Dispose ();
+ _playbin = null;
+ }
+
+ args.RetVal = true;
+ }
+
+ void ButtonOpenClicked (object sender, EventArgs args) {
+ FileChooserDialog dialog = new FileChooserDialog ("Open", this, FileChooserAction.Open, new object[] { "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept });
+ dialog.SetCurrentFolder (Environment.GetFolderPath (Environment.SpecialFolder.Personal));
+
+ if (dialog.Run () == (int) ResponseType.Accept) {
+ _pipelineOK = false;
+
+ if (_playbin != null) {
+ _playbin.SetState (Gst.State.Null);
+ } else {
+ _playbin = ElementFactory.Make ("playbin", "playbin");
+ }
+
+ _scale.Value = 0;
+
+ if (_playbin == null)
+ Console.WriteLine ("Unable to create element 'playbin'");
+
+ _playbin.Bus.EnableSyncMessageEmission ();
+ _playbin.Bus.AddSignalWatch ();
+
+ _playbin.Bus.SyncMessage += delegate (object bus, SyncMessageArgs sargs) {
+ Gst.Message msg = sargs.Message;
+
+ if (!Gst.Video.GlobalVideo.IsVideoOverlayPrepareWindowHandleMessage (msg))
+ return;
+
+ Element src = msg.Src as Element;
+ if (src == null)
+ return;
+
+ try {
+ src["force-aspect-ratio"] = true;
+ }
+ catch (PropertyNotFoundException) {}
+ Element overlay = null;
+ if(src is Gst.Bin)
+ overlay = ((Gst.Bin) src).GetByInterface (VideoOverlayAdapter.GType);
+
+ VideoOverlayAdapter adapter = new VideoOverlayAdapter (overlay.Handle);
+ adapter.WindowHandle = _xWindowId;
+ adapter.HandleEvents (true);
+ };
+
+ _playbin.Bus.Message += delegate (object bus, MessageArgs margs) {
+ Message message = margs.Message;
+
+ switch (message.Type) {
+ case Gst.MessageType.Error:
+ GLib.GException err;
+ string msg;
+
+ message.ParseError (out err, out msg);
+ Console.WriteLine (String.Format ("Error message: {0}", msg));
+ _pipelineOK = false;
+ break;
+ case Gst.MessageType.Eos:
+ Console.WriteLine ("EOS");
+ break;
+ }
+ };
+
+ switch (System.Environment.OSVersion.Platform) {
+ case PlatformID.Unix:
+ _playbin["uri"] = "file://" + dialog.Filename;
+ break;
+ case PlatformID.Win32NT:
+ case PlatformID.Win32S:
+ case PlatformID.Win32Windows:
+ case PlatformID.WinCE:
+ _playbin["uri"] = "file:///" + dialog.Filename.Replace("\\","/");
+ break;
+ }
+
+ StateChangeReturn sret = _playbin.SetState (Gst.State.Playing);
+
+ if (sret == StateChangeReturn.Async) {
+ State state, pending;
+ sret = _playbin.GetState (out state, out pending, Constants.SECOND * 5L);
+ }
+
+ if (sret == StateChangeReturn.Success) {
+ Console.WriteLine ("State change successful");
+ _pipelineOK = true;
+ } else {
+ Console.WriteLine ("State change failed for {0} ({1})\n", dialog.Filename, sret);
+ }
+ }
+
+ dialog.Destroy ();
+ }
+
+ void ButtonPlayClicked (object sender, EventArgs args) {
+ if ( (_playbin != null) && _pipelineOK)
+ _playbin.SetState (Gst.State.Playing);
+ }
+
+ void ButtonPauseClicked (object sender, EventArgs args) {
+ if ( (_playbin != null) && _pipelineOK)
+ _playbin.SetState (Gst.State.Paused);
+ }
+
+ void ScaleValueChanged (object sender, EventArgs args) {
+ if (_updatingScale)
+ return;
+
+ long duration;
+ Gst.Format fmt = Gst.Format.Time;
+ Console.WriteLine ("Trying to seek");
+
+ if ( (_playbin != null) && _pipelineOK && _playbin.QueryDuration (fmt, out duration) && duration != -1) {
+ long pos = (long) (duration * _scale.Value);
+ Console.WriteLine ("Seek to {0}/{1} ({2}%)", pos, duration, _scale.Value);
+
+ bool ret = _playbin.SeekSimple (Format.Time, SeekFlags.Flush | SeekFlags.KeyUnit, pos);
+
+ Console.WriteLine ("Seeked {0}successfully", (ret ? "" : "not "));
+ }
+ }
+
+ bool UpdatePos () {
+ Gst.Format fmt = Gst.Format.Time;
+ long duration, pos;
+ pos = 0;
+ if ( (_playbin != null) && _pipelineOK &&
+ _playbin.QueryDuration (fmt, out duration) &&
+ _playbin.QueryPosition (fmt, out pos)) {
+ _lbl.Text = string.Format ("{0} / {1}", TimeString (pos), TimeString (duration));
+
+ _updatingScale = true;
+ _scale.Value = (double) pos / duration;
+ _updatingScale = false;
+ }
+
+ return true;
+ }
+
+ string TimeString (long t) {
+ long secs = t / 1000000000;
+ int mins = (int) (secs / 60);
+ secs = secs - (mins * 60);
+
+ if (mins >= 60) {
+ int hours = (int) (mins / 60);
+ mins = mins - (hours * 60);
+
+ return string.Format ("{0}:{1:d2}:{2:d2}", hours, mins, secs);
+ }
+
+ return string.Format ("{0}:{1:d2}", mins, secs);
+ }
+
+ [DllImport ("libgdk-3.so.0") ]
+ static extern uint gdk_x11_window_get_xid (IntPtr handle);
+
+ [DllImport ("libgdk-win32-3.0-0.dll") ]
+ static extern IntPtr gdk_win32_drawable_get_handle (IntPtr handle);
+
+ [DllImport ("libX11.so.6")]
+ static extern int XInitThreads ();
+ }
+}