Fix structure handling (almost) of caps
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Sun, 19 Apr 2009 14:53:25 +0000 (16:53 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Sun, 19 Apr 2009 14:56:14 +0000 (16:56 +0200)
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
gstreamer-sharp/Gstreamer.metadata
gstreamer-sharp/Structure.custom

index 7acdbfd..b516a2b 100644 (file)
@@ -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));
+}
index 150db35..724b3e7 100644 (file)
@@ -80,6 +80,7 @@
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_append_structure']" name="hidden">1</attr>
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_append']" name="hidden">1</attr>
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_merge']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_unref']" name="hidden">1</attr>
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_intersect']/return-type" name="owned">true</attr>
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_union']/return-type" name="owned">true</attr>
   <attr path="/api/namespace/boxed[@name='Caps']/method[@cname='gst_caps_normalize']/return-type" name="owned">true</attr>
   <attr path="/api/namespace/boxed[@name='Structure']/method[@cname='gst_structure_fixate_field_nearest_fraction']" name="hidden">1</attr>
   <attr path="/api/namespace/boxed[@name='Structure']/method[@cname='gst_structure_set_valist']" name="hidden">1</attr>
   <attr path="/api/namespace/boxed[@name='Structure']/method[@cname='gst_structure_get_name_id']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[@name='Structure']/method[@cname='gst_structure_free']" name="hidden">1</attr>
   <change-node-type path="/api/namespace/boxed[@name='Structure']/method[@cname='gst_structure_empty_new']">constructor</change-node-type>
   <remove-attr path="/api/namespace/boxed[@name='Structure']/constructor[@cname='gst_structure_empty_new']" name="name" />
   <remove-attr path="/api/namespace/boxed[@name='Structure']/constructor[@cname='gst_structure_empty_new']" name="shared" />
index dcc3c14..96fe7b6 100644 (file)
@@ -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;
+}