From 0c50db66f0e4707c1929c82bf2791d3c402ebf96 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Apr 2009 16:53:25 +0200 Subject: [PATCH] Fix structure handling (almost) of caps Make sure that we a) don't free structures of caps as we don't own them and b) make sure to create a copy of all still referenced structures before it gets removed, the caps are unreffed or something else happens. This still needs to be fixed for gst_caps_do_simplify()! This workaround is inspired by the one in gst-python. --- gstreamer-sharp/Caps.custom | 75 +++++++++++++++++++++++++++++++++++++- gstreamer-sharp/Gstreamer.metadata | 2 + gstreamer-sharp/Structure.custom | 37 +++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/gstreamer-sharp/Caps.custom b/gstreamer-sharp/Caps.custom index 7acdbfd..b516a2b 100644 --- a/gstreamer-sharp/Caps.custom +++ b/gstreamer-sharp/Caps.custom @@ -35,6 +35,7 @@ public void MakeWritable() { if (IsWritable) return; + RemoveStructureReferences (); IntPtr copy = gst_caps_copy (Raw); Raw = copy; /* ^--- Takes a second ref, not good */ @@ -43,6 +44,19 @@ public void MakeWritable() { Owned = true; } +private Hashtable structures = new Hashtable (); + +private void RemoveStructureReference (Structure s) { + structures.Remove (s.Handle); + s.CreateNativeCopy (); +} + +private void RemoveStructureReferences () { + foreach (Structure s in structures.Values) { + RemoveStructureReference (s); + } +} + [DllImport ("gstreamer-0.10.dll") ] private static extern IntPtr gst_caps_get_structure (IntPtr handle, uint index); @@ -53,7 +67,18 @@ public Structure this [uint index] { IntPtr raw_ptr = gst_caps_get_structure (Handle, (uint) index); - return (Gst.Structure) new Gst.Structure (raw_ptr); + if (structures.Contains (raw_ptr)) { + Structure ret = (Gst.Structure) structures[raw_ptr]; + + return ret; + } else { + Structure ret = new Gst.Structure (raw_ptr); + + ret.FreeNative = false; + structures.Add (raw_ptr, ret); + + return ret; + } } } @@ -131,6 +156,10 @@ public void Merge (Caps caps) { if (!IsWritable) throw new ApplicationException (); + /* Removes all structures! */ + if (caps.IsAny) { + RemoveStructureReferences (); + } gst_caps_merge (Handle, gst_caps_copy (caps.Handle)); } @@ -143,6 +172,10 @@ public void RemoveStructure (uint index) { if (index >= Size) throw new ArgumentOutOfRangeException (); + if (structures.Contains (this[index].Handle)) { + RemoveStructureReference (this[index]); + } + gst_caps_remove_structure (Handle, index); } @@ -153,6 +186,10 @@ public bool DoSimplify () { if (!IsWritable) throw new ApplicationException (); + /* FIXME: This might remove/free structures, we have to copy + * them before with RemoveStructureReference() somehow + */ + return gst_caps_do_simplify (Handle); } @@ -163,5 +200,41 @@ public void Truncate () { if (!IsWritable) throw new ApplicationException (); + for (uint i = 1; i < Size; i++) + RemoveStructureReference (this[i]); + gst_caps_truncate (Handle); } + +[DllImport ("gstreamer-0.10.dll") ] +static extern void gst_caps_unref (IntPtr raw); + +protected override void Unref (IntPtr raw) { + RemoveStructureReferences (); + if (Owned) { + gst_caps_unref (raw); + Owned = false; + } +} + +class FinalizerInfo { + IntPtr handle; + + public FinalizerInfo (IntPtr handle) { + this.handle = handle; + } + + public bool Handler () { + gst_caps_unref (handle); + return false; + } +} + +~Caps () { + if (!Owned) + return; + RemoveStructureReferences (); + + FinalizerInfo info = new FinalizerInfo (Handle); + GLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler)); +} diff --git a/gstreamer-sharp/Gstreamer.metadata b/gstreamer-sharp/Gstreamer.metadata index 150db35..724b3e7 100644 --- a/gstreamer-sharp/Gstreamer.metadata +++ b/gstreamer-sharp/Gstreamer.metadata @@ -80,6 +80,7 @@ 1 1 1 + 1 true true true @@ -407,6 +408,7 @@ 1 1 1 + 1 constructor diff --git a/gstreamer-sharp/Structure.custom b/gstreamer-sharp/Structure.custom index dcc3c14..96fe7b6 100644 --- a/gstreamer-sharp/Structure.custom +++ b/gstreamer-sharp/Structure.custom @@ -1,3 +1,35 @@ +internal bool FreeNative = true; + +[DllImport ("gstreamer-0.10.dll") ] +static extern void gst_structure_free (IntPtr raw); + +protected override void Free (IntPtr raw) { + if (!FreeNative) + return; + + gst_structure_free (raw); +} + +class FinalizerInfo { + IntPtr handle; + + public FinalizerInfo (IntPtr handle) { + this.handle = handle; + } + + public bool Handler () { + gst_structure_free (handle); + return false; + } +} + +~Structure () { + if (!Owned || !FreeNative) + return; + FinalizerInfo info = new FinalizerInfo (Handle); + GLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler)); +} + [DllImport ("gstreamer-0.10.dll") ] static extern IntPtr gst_structure_get_name (IntPtr raw); @@ -199,3 +231,8 @@ public bool IsMutable { } } +internal void CreateNativeCopy () { + FreeNative = false; + Raw = gst_structure_copy (Raw); + FreeNative = true; +} -- 2.7.4