Also add a XvImageSink binding and add the GtkVideoPlayer sample
from the above place.
This commit is contained in:
Sebastian Dröge 2009-05-21 20:57:26 +02:00
parent e028718bb3
commit c54dc8ce93
4 changed files with 385 additions and 134 deletions

View file

@ -0,0 +1,54 @@
using System;
using System.Runtime.InteropServices;
using Gst;
using Gst.Interfaces;
namespace Gst.BasePlugins {
[GTypeName ("GstXvImageSink") ]
public class XvImageSink : Element, XOverlay {
public XvImageSink (IntPtr raw) : base (raw) { }
public static XvImageSink Make (string name) {
return ElementFactory.Make ("xvimagesink", name) as XvImageSink;
}
[DllImport ("gstinterfaces-0.10.dll") ]
static extern void gst_x_overlay_expose (IntPtr raw);
public void Expose() {
gst_x_overlay_expose (Handle);
}
[DllImport ("gstinterfaces-0.10.dll") ]
static extern void gst_x_overlay_handle_events (IntPtr raw, bool handle_events);
public void HandleEvents (bool handle_events) {
gst_x_overlay_handle_events (Handle, handle_events);
}
[DllImport ("gstinterfaces-0.10.dll") ]
static extern void gst_x_overlay_got_xwindow_id (IntPtr raw, UIntPtr xwindow_id);
public void GotXwindowId (ulong xwindow_id) {
gst_x_overlay_got_xwindow_id (Handle, new UIntPtr (xwindow_id));
}
[DllImport ("gstinterfaces-0.10.dll") ]
static extern void gst_x_overlay_prepare_xwindow_id (IntPtr raw);
public void PrepareXwindowId() {
gst_x_overlay_prepare_xwindow_id (Handle);
}
[DllImport ("gstinterfaces-0.10.dll") ]
static extern void gst_x_overlay_set_xwindow_id (IntPtr raw, UIntPtr xwindow_id);
public ulong XwindowId {
set {
gst_x_overlay_set_xwindow_id (Handle, new UIntPtr (value));
}
}
}
}

188
samples/GtkVideoPlayer.cs Normal file
View file

@ -0,0 +1,188 @@
// Authors
// Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
using System;
using System.Runtime.InteropServices;
using Gtk;
using Gst;
using Gst.Interfaces;
using Gst.BasePlugins;
public class MainWindow : Gtk.Window {
DrawingArea _da;
Pipeline _pipeline;
HScale _scale;
Label _lbl;
bool _updatingScale;
bool _pipelineOK;
public static void Main (string[] args) {
Gtk.Application.Init ();
Gst.Application.Init ();
MainWindow window = new MainWindow ();
window.ShowAll ();
Gtk.Application.Run ();
}
public MainWindow ()
: base (WindowType.Toplevel) {
VBox vBox = new VBox ();
_da = new DrawingArea ();
_da.ModifyBg (Gtk.StateType.Normal, new Gdk.Color (0, 0, 0));
_da.SetSizeRequest (400, 300);
vBox.PackStart (_da);
_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 ();
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 (_pipeline != null) {
_pipeline.SetState (Gst.State.Null);
_pipeline.Dispose ();
}
_scale.Value = 0;
_pipeline = new Pipeline (string.Empty);
Element playbin = ElementFactory.Make ("playbin", "playbin");
XvImageSink sink = XvImageSink.Make ("sink");
if (_pipeline == null)
Console.WriteLine ("Unable to create pipeline");
if (playbin == null)
Console.WriteLine ("Unable to create element 'playbin'");
if (sink == null)
Console.WriteLine ("Unable to create element 'sink'");
_pipeline.Add (playbin);
sink.XwindowId = gdk_x11_drawable_get_xid (_da.GdkWindow.Handle);
playbin["video-sink"] = sink;
playbin["uri"] = "file://" + dialog.Filename;
StateChangeReturn sret = _pipeline.SetState (Gst.State.Playing);
if (sret == StateChangeReturn.Async) {
State state, pending;
sret = _pipeline.GetState (out state, out pending, Clock.Second * 5);
}
if (sret == StateChangeReturn.Success)
_pipelineOK = true;
else
Console.WriteLine ("State change failed for {0} ({1})\n", dialog.Filename, sret);
}
dialog.Destroy ();
}
void ButtonPlayClicked (object sender, EventArgs args) {
if ( (_pipeline != null) && _pipelineOK)
_pipeline.SetState (Gst.State.Playing);
}
void ButtonPauseClicked (object sender, EventArgs args) {
if ( (_pipeline != null) && _pipelineOK)
_pipeline.SetState (Gst.State.Paused);
}
void ScaleValueChanged (object sender, EventArgs args) {
if (_updatingScale)
return;
long duration;
Gst.Format fmt = Gst.Format.Time;
if ( (_pipeline != null) && _pipelineOK && _pipeline.QueryDuration (ref fmt, out duration)) {
long pos = (long) (duration * _scale.Value);
//Console.WriteLine ("Seek to {0}/{1} ({2}%)", pos, duration, _scale.Value);
_pipeline.Seek (Format.Time, SeekFlags.Flush, pos);
}
}
bool UpdatePos () {
Gst.Format fmt = Gst.Format.Time;
long duration, pos;
if ( (_pipeline != null) && _pipelineOK &&
_pipeline.QueryDuration (ref fmt, out duration) &&
_pipeline.QueryPosition (ref 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-x11-2.0") ]
static extern uint gdk_x11_drawable_get_xid (IntPtr handle);
}

View file

@ -1,4 +1,4 @@
TARGETS = playbin-player.exe decodebin-transcoder.exe helloworld.exe typefind.exe TARGETS = playbin-player.exe decodebin-transcoder.exe helloworld.exe typefind.exe metadata.exe gtk-video-player.exe
DEBUGS = $(addsuffix .mdb, $(TARGETS)) DEBUGS = $(addsuffix .mdb, $(TARGETS))
all: $(TARGETS) link all: $(TARGETS) link
@ -28,6 +28,9 @@ metadata.exe: $(srcdir)/MetaData.cs $(assemblies)
mp3launchparse.exe: $(srcdir)/MP3LaunchParse.cs $(assemblies) mp3launchparse.exe: $(srcdir)/MP3LaunchParse.cs $(assemblies)
$(CSC) -out:$@ $(GLIBSHARP_LIBS) $(references) $(srcdir)/MP3LaunchParse.cs $(CSC) -out:$@ $(GLIBSHARP_LIBS) $(references) $(srcdir)/MP3LaunchParse.cs
gtk-video-player.exe: $(srcdir)/GtkVideoPlayer.cs $(assemblies)
$(CSC) $(GLIBSHARP_LIBS) $(references) -pkg:gtk-sharp-2.0 $(srcdir)/GtkVideoPlayer.cs /out:gtk-video-player.exe
link: link:
ln -sf $(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll gstreamer-sharp.dll ln -sf $(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll gstreamer-sharp.dll
ln -sf $(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll.config gstreamer-sharp.dll.config ln -sf $(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll.config gstreamer-sharp.dll.config

View file

@ -1,161 +1,167 @@
//
// Authors // Authors
// Khaled Mohammed (khaled.mohammed@gmail.com) // Copyright (C) 2006 Khaled Mohammed <khaled.mohammed@gmail.com>
// // Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
// (C) 2006
// using System;
using System.IO;
using Gst; using Gst;
using System;
public class MetaData public class MetaData {
{ static Element pipeline = null;
static Element source = null;
static Element pipeline = null; static void PrintTag (TagList list, string tag) {
static Element source = null; uint count = list.GetTagSize (tag);
static void PrintTag( TagList list, string tag) { //Console.WriteLine ("Tags found = " + count);
uint count = list.GetTagSize(tag);
Console.WriteLine("Tags found = " + count);
for(uint i =0; i < count; i++)
{
string str;
if(Tag.GetGType(tag) == GLib.GType.String) {
if(!list.GetStringIndex(tag, i, out str))
Console.Error.WriteLine("g_assert_not_reached()???");
} else {
str = (String) list.GetValueIndex(tag, i).Val;
}
if(i == 0) for (uint i = 0; i < count; i++) {
Console.WriteLine("{0}:\t {1}", Tag.GetNick(tag), str); string str;
else
Console.WriteLine("\t{0}", str);
}
}
static bool MessageLoop(Element element, ref TagList tags) try {
{ str = list[tag, i].ToString ();
Bus bus = element.Bus; } catch (Exception ex) {
bool done = false; str = ex.Message;
}
while(!done) { if (i == 0)
Message message = bus.Pop(); Console.WriteLine ("{0}: {1}", Tag.GetNick (tag).PadRight (25), str);
if(message == null) else
break; Console.WriteLine ("{0}{1}", string.Empty.PadRight (27), str);
}
}
switch(message.Type) { static bool MessageLoop (Element element, ref TagList tags) {
case MessageType.Error: Bus bus = element.Bus;
string error; bool done = false;
message.ParseError(out error);
message.Dispose();
return true;
case MessageType.Eos:
message.Dispose();
return true;
case MessageType.Tag: {
TagList new_tags = new TagList();
message.ParseTag(new_tags);
if(tags != null) {
tags = tags.Merge(new_tags, TagMergeMode.KeepAll);
}
else {
tags = new_tags;
}
//tags.Foreach(PrintTag);
//new_tags.Dispose();
break;
}
default:
break;
}
message.Dispose();
}
bus.Dispose();
return true;
}
static void MakePipeline() while (!done) {
{ Message message = bus.Pop ();
Element decodebin;
if(pipeline != null) { if (message == null)
pipeline.Dispose(); break;
}
pipeline = new Pipeline(String.Empty);
source = ElementFactory.Make("filesrc", "source");
decodebin = ElementFactory.Make("decodebin", "decodebin");
if(pipeline == null) Console.Error.WriteLine("Pipeline count not be created"); switch (message.Type) {
if(source == null) Console.Error.WriteLine("Element filesrc could not be created"); case MessageType.Error:
if(decodebin == null) Console.Error.WriteLine("Element decodebin coult not be created"); Enum error;
string msg;
message.ParseError (out error, out msg);
message.Dispose ();
return true;
Bin bin = (Bin) pipeline; case MessageType.Eos:
bin.AddMany(source, decodebin); message.Dispose ();
if(!source.Link(decodebin)) return true;
Console.Error.WriteLine("filesrc could not be linked with decodebin");
decodebin.Dispose();
}
public static void Main(string [] args) case MessageType.Tag:
{ TagList new_tags;
Application.Init();
if(args.Length < 1) message.ParseTag (out new_tags);
{
Console.Error.WriteLine("Please give filenames to read metadata from\n\n");
return;
}
MakePipeline(); if (tags != null) {
tags = tags.Merge (new_tags, TagMergeMode.KeepAll);
new_tags.Dispose ();
} else
tags = new_tags;
int i=-1; break;
while(++i < args.Length)
{
State state, pending;
TagList tags = null;
string filename = args[i]; default:
source.SetProperty("location", filename); break;
}
StateChangeReturn sret = pipeline.SetState(State.Paused); message.Dispose ();
}
if(sret == StateChangeReturn.Async) { bus.Dispose ();
if(StateChangeReturn.Success != pipeline.GetState(out state, out pending, Clock.Second * 5)) { return true;
Console.Error.WriteLine("State change failed for {0}. Aborting\n", filename); }
break;
}
} else if(sret != StateChangeReturn.Success) {
Console.Error.WriteLine("{0} - Could not read file\n", filename);
continue;
}
if(!MessageLoop(pipeline, ref tags)) { static void MakePipeline () {
Console.Error.WriteLine("Failed in message reading for {0}", args[i]); Element decodebin;
}
if(tags != null) { if (pipeline != null)
Console.WriteLine("Metadata for {0}:", args[i]); pipeline.Dispose ();
tags.Foreach(new TagForeachFunc(PrintTag));
tags.Dispose();
tags = null;
} else Console.Error.WriteLine("No metadata found for {0}", args[0]);
sret = pipeline.SetState(State.Null); pipeline = new Pipeline (String.Empty);
source = ElementFactory.Make ("filesrc", "source");
decodebin = ElementFactory.Make ("decodebin", "decodebin");
if(StateChangeReturn.Async == sret) { if (pipeline == null)
if(StateChangeReturn.Failure == pipeline.GetState(out state, out pending, Clock.TimeNone)) { Console.WriteLine ("Pipeline could not be created");
Console.Error.WriteLine("State change failed. Aborting"); if (source == null)
} Console.WriteLine ("Element filesrc could not be created");
} if (decodebin == null)
} Console.WriteLine ("Element decodebin could not be created");
if(pipeline != null) Bin bin = (Bin) pipeline;
{ bin.Add (source, decodebin);
pipeline.Dispose();
}
} if (!source.Link (decodebin))
Console.WriteLine ("filesrc could not be linked with decodebin");
//decodebin.Dispose ();
}
public static void Main (string [] args) {
Application.Init ();
if (args.Length < 1) {
Console.WriteLine ("Please give filenames to read metadata from\n\n");
return;
}
MakePipeline ();
int i = -1;
while (++i < args.Length) {
State state, pending;
TagList tags = null;
string filename = args[i];
if (!File.Exists (filename)) {
Console.WriteLine ("File {0} does not exist", filename);
continue;
}
source["location"] = filename;
StateChangeReturn sret = pipeline.SetState (State.Paused);
if (sret == StateChangeReturn.Async) {
if (StateChangeReturn.Success != pipeline.GetState (out state, out pending, Clock.Second * 5)) {
Console.WriteLine ("State change failed for {0}. Aborting\n", filename);
break;
}
} else if (sret != StateChangeReturn.Success) {
Console.WriteLine ("{0} - Could not read file ({1})\n", filename, sret);
continue;
}
if (!MessageLoop (pipeline, ref tags))
Console.Error.WriteLine ("Failed in message reading for {0}", args[i]);
if (tags != null) {
Console.WriteLine ("Metadata for {0}:", filename);
foreach (string tag in tags.Tags)
PrintTag (tags, tag);
tags.Dispose ();
tags = null;
} else
Console.WriteLine ("No metadata found for {0}", args[0]);
sret = pipeline.SetState (State.Null);
if (StateChangeReturn.Async == sret) {
if (StateChangeReturn.Failure == pipeline.GetState (out state, out pending, Clock.TimeNone))
Console.WriteLine ("State change failed. Aborting");
}
}
if (pipeline != null)
pipeline.Dispose ();
}
} }