mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-21 07:46:38 +00:00
9713ead713
This caused crashes for caps with more than a single struct when unreffing them in one way or another. Fixes bug #627677.
250 lines
5.5 KiB
Text
250 lines
5.5 KiB
Text
public static Gst.Caps NewEmpty () {
|
|
return new Gst.Caps ();
|
|
}
|
|
|
|
public Caps (Structure s) : this () {
|
|
Append (s);
|
|
}
|
|
|
|
public Caps (Structure[] s) : this () {
|
|
foreach (Structure o in s)
|
|
Append (o);
|
|
}
|
|
|
|
public Caps (string mediaType, params object[] fields) : this () {
|
|
Append (new Structure (mediaType, fields));
|
|
}
|
|
|
|
[DllImport ("gstreamersharpglue-0.10.dll") ]
|
|
extern static uint gstsharp_gst_caps_get_refcount_offset ();
|
|
|
|
static uint refcount_offset = gstsharp_gst_caps_get_refcount_offset ();
|
|
private int Refcount {
|
|
get {
|
|
unsafe {
|
|
int* raw_ptr = (int*) ( ( (byte*) Handle) + refcount_offset);
|
|
return (*raw_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsWritable {
|
|
get {
|
|
return (Refcount == 1);
|
|
}
|
|
}
|
|
|
|
/* FIXME: This is not optimal! */
|
|
public void MakeWritable() {
|
|
if (IsWritable)
|
|
return;
|
|
|
|
RemoveStructureReferences ();
|
|
IntPtr copy = gst_caps_copy (Raw);
|
|
Raw = copy;
|
|
/* ^--- Takes a second ref, not good */
|
|
Unref (Raw);
|
|
/* ^--- Sets Owned = false, wrong! */
|
|
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) {
|
|
s.CreateNativeCopy ();
|
|
}
|
|
structures.Clear ();
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
private static extern IntPtr gst_caps_get_structure (IntPtr handle, uint index);
|
|
|
|
public Structure this [uint index] {
|
|
get {
|
|
if (index >= Size)
|
|
throw new ArgumentOutOfRangeException ();
|
|
|
|
IntPtr raw_ptr = gst_caps_get_structure (Handle, (uint) index);
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class StructureEnumerator : IEnumerator {
|
|
Gst.Caps caps;
|
|
long index;
|
|
|
|
public StructureEnumerator (Gst.Caps caps) {
|
|
this.caps = caps;
|
|
index = -1;
|
|
}
|
|
|
|
public object Current {
|
|
get {
|
|
if (index >= caps.Size)
|
|
throw new ArgumentOutOfRangeException ();
|
|
if (index == -1)
|
|
throw new ArgumentException ();
|
|
|
|
return caps[ (uint) index];
|
|
}
|
|
}
|
|
|
|
public bool MoveNext () {
|
|
index += 1;
|
|
return (index < caps.Size);
|
|
}
|
|
|
|
public void Reset () {
|
|
index = -1;
|
|
}
|
|
}
|
|
|
|
public IEnumerator GetEnumerator() {
|
|
return new StructureEnumerator (this);
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_append_structure (IntPtr caps, IntPtr structure);
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern IntPtr gst_structure_copy (IntPtr raw);
|
|
|
|
public void Append (Structure s) {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
|
|
gst_caps_append_structure (Handle, gst_structure_copy (s.Handle));
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_append (IntPtr caps, IntPtr caps2);
|
|
|
|
public void Append (Caps caps) {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
|
|
gst_caps_append (Handle, gst_caps_copy (caps.Handle));
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_merge_structure (IntPtr caps, IntPtr structure);
|
|
|
|
public void Merge (Structure s) {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
|
|
gst_caps_merge_structure (Handle, gst_structure_copy (s.Handle));
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_merge (IntPtr caps, IntPtr caps2);
|
|
|
|
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));
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_remove_structure (IntPtr caps, uint index);
|
|
|
|
public void RemoveStructure (uint index) {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
if (index >= Size)
|
|
throw new ArgumentOutOfRangeException ();
|
|
|
|
if (structures.Contains (this[index].Handle)) {
|
|
RemoveStructureReference (this[index]);
|
|
}
|
|
|
|
gst_caps_remove_structure (Handle, index);
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern bool gst_caps_do_simplify (IntPtr caps);
|
|
|
|
public bool DoSimplify () {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
|
|
/* FIXME: This is not optimal but we don't know before
|
|
* which structures will be removed */
|
|
RemoveStructureReferences ();
|
|
|
|
return gst_caps_do_simplify (Handle);
|
|
}
|
|
|
|
[DllImport ("libgstreamer-0.10.dll") ]
|
|
static extern void gst_caps_truncate (IntPtr caps);
|
|
|
|
public void Truncate () {
|
|
if (!IsWritable)
|
|
throw new ApplicationException ();
|
|
|
|
for (uint i = 1; i < Size; i++)
|
|
RemoveStructureReference (this[i]);
|
|
|
|
gst_caps_truncate (Handle);
|
|
}
|
|
|
|
[DllImport ("libgstreamer-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);
|
|
Gst.GLib.Timeout.Add (50, new Gst.GLib.TimeoutHandler (info.Handler));
|
|
}
|
|
|
|
protected override Gst.GLib.Opaque Copy (IntPtr raw) {
|
|
return Gst.GLib.Opaque.GetOpaque (gst_caps_ref (raw), typeof (Caps), true);
|
|
}
|
|
|