diff --git a/gst/gst_message.go b/gst/gst_message.go index c5880b8..91fcfd8 100644 --- a/gst/gst_message.go +++ b/gst/gst_message.go @@ -95,9 +95,7 @@ func (m *Message) GetStructure() *Structure { return nil } - // The returned structure must not be freed. Applies to all methods. - // https://gstreamer.freedesktop.org/documentation/gstreamer/gstmessage.html#gst_message_parse_error_details - return wrapStructure(st) + return structureFromGlibNone(st) } // parseToError returns a new GError from this message instance. There are multiple diff --git a/gst/gst_structure.go b/gst/gst_structure.go index e33ab2c..3c6f605 100644 --- a/gst/gst_structure.go +++ b/gst/gst_structure.go @@ -17,6 +17,7 @@ import ( "fmt" "os" "reflect" + "runtime" "sync" "unsafe" @@ -35,7 +36,7 @@ func NewStructure(name string) *Structure { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) structure := C.gst_structure_new_empty(cName) - return wrapStructure(structure) + return structureFromGlibFull(structure) } // NewStructureFromString builds a new GstStructure from the given string. @@ -46,7 +47,7 @@ func NewStructureFromString(stStr string) *Structure { if structure == nil { return nil } - return wrapStructure(structure) + return structureFromGlibFull(structure) } // MarshalStructure will convert the given go struct into a GstStructure. Currently nested @@ -190,22 +191,54 @@ var TypeStructure = glib.Type(C.gst_structure_get_type()) var _ glib.ValueTransformer = &Structure{} +func (s *Structure) copy() *C.GstStructure { + return C.gst_structure_copy(s.Instance()) +} + // ToGValue implements a glib.ValueTransformer func (s *Structure) ToGValue() (*glib.Value, error) { val, err := glib.ValueInit(TypeStructure) if err != nil { return nil, err } + C.gst_value_set_structure( (*C.GValue)(unsafe.Pointer(val.GValue)), - s.Instance(), + s.copy(), ) return val, nil } +// marshalStructure is used to extract the GstStructure from a GValue. +func marshalStructure(p unsafe.Pointer) (interface{}, error) { + c := C.gst_value_get_structure(toGValue(p)) + obj := (*C.GstStructure)(unsafe.Pointer(c)) + return structureFromGlibNone(obj), nil +} + func wrapStructure(st *C.GstStructure) *Structure { return &Structure{ ptr: unsafe.Pointer(st), gType: glib.Type(st._type), } } + +// structureFromGlibNone wraps a *C.GstStructure in a Structure after copying it. +// this is needed when the structure is returned from a function that does not transfer ownership. +func structureFromGlibNone(st *C.GstStructure) *Structure { + copy := C.gst_structure_copy(st) + + return structureFromGlibFull(copy) +} + +// structureFromGlibFull wraps a *C.GstStructure in a Structure. This is used when the structure +// is returned by a function that transfers ownership to the caller. +func structureFromGlibFull(st *C.GstStructure) *Structure { + s := wrapStructure(st) + + runtime.SetFinalizer(s, func(s *Structure) { + s.Free() + }) + + return s +} diff --git a/gst/gst_values.go b/gst/gst_values.go index 22ed2b5..1e50597 100644 --- a/gst/gst_values.go +++ b/gst/gst_values.go @@ -161,16 +161,6 @@ func ValueGetCapsFeatures(value *glib.Value) *CapsFeatures { return &CapsFeatures{native: feats} } -// ValueGetStructure extracts the GstStructure from a glib.Value, or nil -// if one does not exist. -func ValueGetStructure(gval *glib.Value) *Structure { - st := C.gst_value_get_structure((*C.GValue)(unsafe.Pointer(gval.GValue))) - if st == nil { - return nil - } - return wrapStructure(st) -} - // ValueIntersect calculates the intersection of two values. If the values have a non-empty intersection, // the value representing the intersection isreturned. Otherwise this function returns false. This function // can also return false for any allocation errors. diff --git a/gst/gst_wrappers.go b/gst/gst_wrappers.go index 64659f9..cdac909 100644 --- a/gst/gst_wrappers.go +++ b/gst/gst_wrappers.go @@ -461,12 +461,6 @@ func marshalCapsFeatures(p unsafe.Pointer) (interface{}, error) { return wrapCapsFeatures(obj), nil } -func marshalStructure(p unsafe.Pointer) (interface{}, error) { - c := C.gst_value_get_structure(toGValue(p)) - obj := (*C.GstStructure)(unsafe.Pointer(c)) - return wrapStructure(obj), nil -} - func marshalContext(p unsafe.Pointer) (interface{}, error) { c := C.g_value_get_object(toGValue(p)) obj := (*C.GstContext)(unsafe.Pointer(c))