Files
go-gst/gst/gst_caps.go
2021-01-19 00:18:30 +02:00

488 lines
18 KiB
Go

package gst
/*
#include "gst.go.h"
extern gboolean goCapsMapFunc (GstCapsFeatures * features, GstStructure * structure, gpointer user_data);
gboolean cgoCapsMapFunc (GstCapsFeatures * features, GstStructure * structure, gpointer user_data)
{
return goCapsMapFunc(features, structure, user_data);
}
*/
import "C"
import (
"runtime"
"unsafe"
gopointer "github.com/mattn/go-pointer"
"github.com/tinyzimmer/go-glib/glib"
)
// TypeCaps is the static Glib Type for a GstCaps.
var TypeCaps = glib.Type(C.gst_caps_get_type())
// Caps is a go wrapper around GstCaps.
type Caps struct {
native *C.GstCaps
}
// FromGstCapsUnsafeNone wraps the pointer to the given C GstCaps with the go type.
// This is meant for internal usage and is exported for visibility to other packages.
// A ref is taken on the caps and finalizer placed on the object.
func FromGstCapsUnsafeNone(caps unsafe.Pointer) *Caps {
if caps == nil {
return nil
}
gocaps := wrapCaps(C.toGstCaps(caps))
gocaps.Ref()
runtime.SetFinalizer(gocaps, (*Caps).Unref)
return gocaps
}
// // FromGstCapsUnsafe is an alias to FromGstCapsUnsafeNone.
// func FromGstCapsUnsafe(caps unsafe.Pointer) *Caps {
// return FromGstCapsUnsafeNone(caps)
// }
// FromGstCapsUnsafeFull wraps the pointer to the given C GstCaps with the go type.
// This is meant for internal usage and is exported for visibility to other packages.
// A finalizer is placed on the object to Unref after leaving scope.
func FromGstCapsUnsafeFull(caps unsafe.Pointer) *Caps {
if caps == nil {
return nil
}
gocaps := wrapCaps(C.toGstCaps(caps))
runtime.SetFinalizer(gocaps, (*Caps).Unref)
return gocaps
}
// CapsMapFunc represents a function passed to the Caps MapInPlace, ForEach, and FilterAndMapInPlace methods.
type CapsMapFunc func(features *CapsFeatures, structure *Structure) bool
// NewAnyCaps creates a new caps that indicate compatibility with any format.
//
// caps := gst.NewAnyCaps()
// fmt.Println(caps.IsAny())
// // true
//
func NewAnyCaps() *Caps { return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_new_any())) }
// NewEmptyCaps creates a new empty caps object. This is essentially the opposite of
// NewAnyCamps.
//
// caps := gst.NewEmptyCaps()
// fmt.Println(caps.IsEmpty())
// // true
//
func NewEmptyCaps() *Caps { return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_new_empty())) }
// NewEmptySimpleCaps returns a new empty caps object with the given media format.
//
// caps := gst.NewEmptySimpleCaps("audio/x-raw")
// fmt.Println(caps.String())
// // audio/x-raw
//
func NewEmptySimpleCaps(mediaFormat string) *Caps {
cFormat := C.CString(mediaFormat)
defer C.free(unsafe.Pointer(cFormat))
caps := C.gst_caps_new_empty_simple(cFormat)
return FromGstCapsUnsafeFull(unsafe.Pointer(caps))
}
// NewFullCaps creates a new caps from the given structures.
func NewFullCaps(structures ...*Structure) *Caps {
caps := NewEmptyCaps()
for _, st := range structures {
caps.AppendStructure(st)
}
return caps
}
// NewCapsFromString creates a new Caps object from the given string.
//
// caps := gst.NewCapsFromString("audio/x-raw, channels=2")
// fmt.Println(caps.String())
// // audio/x-raw, channels=(int)2
//
func NewCapsFromString(capsStr string) *Caps {
cStr := C.CString(capsStr)
defer C.free(unsafe.Pointer(cStr))
caps := C.gst_caps_from_string(cStr)
if caps == nil {
return nil
}
return FromGstCapsUnsafeFull(unsafe.Pointer(caps))
}
// Unsafe returns an unsafe.Pointer to the underlying GstCaps.
func (c *Caps) Unsafe() unsafe.Pointer { return unsafe.Pointer(c.native) }
// ToGValue returns a GValue containing the given caps. Note that under unexpected circumstances in allocation
// this function can return nil. A reference to these caps is taken by the resulting value, so they are safe to
// unref if not needed anymore. This method is intended for producing values that are needed elsewhere. If you
// are not going to use the value, call Unset.
func (c *Caps) ToGValue() *glib.Value {
val, err := glib.ValueInitUnowned(glib.Type(C.getCapsType()))
if err != nil {
return nil
}
C.gst_value_set_caps((*C.GValue)(unsafe.Pointer(val.GValue)), c.Instance())
return val
}
// Ref increases the ref count on these caps by one.
//
// From this point on, until the caller calls Unref or MakeWritable, it is guaranteed that the caps object
// will not change. This means its structures won't change, etc. To use a Caps object, you must always have a
// refcount on it -- either the one made implicitly by e.g. NewSimpleCaps, or via taking one explicitly with
// this function. Note that when a function provided by these bindings returns caps, or they are converted
// through the FromGstCapsUnsafe methods, a ref is automatically taken if necessary and a runtime Finalizer
// is used to remove it.
func (c *Caps) Ref() *Caps {
C.gst_caps_ref(c.Instance())
return c
}
// Unref decreases the ref count on these caps by one.
func (c *Caps) Unref() { C.gst_caps_unref(c.Instance()) }
// Instance returns the native GstCaps instance
func (c *Caps) Instance() *C.GstCaps { return C.toGstCaps(c.Unsafe()) }
// MakeWritable returns a writable copy of caps.
func (c *Caps) MakeWritable() *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.makeCapsWritable(c.Instance())))
}
// String implements a stringer on a caps instance. This same string can be used for NewCapsFromString.
func (c *Caps) String() string {
cStr := C.gst_caps_to_string(c.Instance())
defer C.g_free((C.gpointer)(unsafe.Pointer(cStr)))
return C.GoString(cStr)
}
// AppendStructure appends the given structure to this caps instance.
func (c *Caps) AppendStructure(st *Structure) {
C.gst_caps_append_structure(c.Instance(), st.Instance())
}
// AppendStructureFull appends structure with features to caps. The structure is not copied;
// caps becomes the owner of structure.
func (c *Caps) AppendStructureFull(st *Structure, features *CapsFeatures) {
C.gst_caps_append_structure_full(c.Instance(), st.Instance(), features.Instance())
}
// Append appends the given caps element to these caps. These caps take ownership
// over the given object. If either caps are ANY, the resulting caps will be ANY.
func (c *Caps) Append(caps *Caps) {
C.gst_caps_append(c.Instance(), caps.Ref().Instance())
}
// CanIntersect tries intersecting these caps with those given and reports whether the result would not be empty.
func (c *Caps) CanIntersect(caps *Caps) bool {
return gobool(C.gst_caps_can_intersect(c.Instance(), caps.Instance()))
}
// Copy creates a new Caps as a copy of these. The new caps will have a refcount of 1, owned by the caller.
// The structures are copied as well.
//
// Note that this function is the semantic equivalent of a Ref followed by a MakeWritable. If you only want to hold
// on to a reference to the data, you should use Ref.
//
// When you are finished with the caps, call Unref on it.
func (c *Caps) Copy() *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_copy(c.Instance())))
}
// CopyNth creates a new GstCaps and appends a copy of the nth structure contained in caps.
func (c *Caps) CopyNth(n uint) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_copy_nth(c.Instance(), C.guint(n))))
}
// FilterAndMapInPlace calls the provided function once for each structure and caps feature in the Caps.
// In contrast to ForEach, the function may modify the structure and features. In contrast to MapInPlace,
// the structure and features are removed from the caps if FALSE is returned from the function. The caps must be mutable.
//
// caps := gst.NewCapsFromString("audio/x-raw")
//
// caps.FilterAndMapInPlace(func(features *gst.CapsFeatures, structure *gst.Structure) bool {
// if features.Contains(gst.CapsFeatureMemorySystemMemory) {
// fmt.Println("Removing system memory feature")
// return false
// }
// return true
// })
//
// fmt.Println(caps.IsEmpty())
//
// // Removing system memory feature
// // true
//
func (c *Caps) FilterAndMapInPlace(f CapsMapFunc) {
ptr := gopointer.Save(f)
defer gopointer.Unref(ptr)
C.gst_caps_filter_and_map_in_place(
c.Instance(),
C.GstCapsFilterMapFunc(C.cgoCapsMapFunc),
(C.gpointer)(ptr),
)
}
// Fixate modifies the given caps into a representation with only fixed values. First the caps will be truncated and
// then the first structure will be fixated with Structure's Fixate.
//
// This function takes ownership of caps and will call gst_caps_make_writable on it so you must not use caps afterwards
// unless you keep an additional reference to it with Ref.
//
// Note that it is not guaranteed that the returned caps have exactly one structure. If caps are empty caps then then
// returned caps will be the empty too and contain no structure at all.
//
// Calling this function with any caps is not allowed.
func (c *Caps) Fixate() *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_fixate(c.Ref().Instance())))
}
// ForEach calls the provided function once for each structure and caps feature in the GstCaps. The function must not
// modify the fields. There is an unresolved bug in this function currently and it is better to use MapInPlace instead.
//
// caps := gst.NewCapsFromString("audio/x-raw")
//
// caps.ForEach(func(features *gst.CapsFeatures, structure *gst.Structure) bool {
// fmt.Println(structure)
// return true
// })
//
// // audio/x-raw;
//
func (c *Caps) ForEach(f CapsMapFunc) bool {
ptr := gopointer.Save(f)
defer gopointer.Unref(ptr)
return gobool(C.gst_caps_foreach(
c.Instance(),
C.GstCapsForeachFunc(C.cgoCapsMapFunc),
(C.gpointer)(ptr),
))
}
// GetSize returns the number of structures inside this caps instance.
func (c *Caps) GetSize() int { return int(C.gst_caps_get_size(c.Instance())) }
// GetStructureAt returns the structure at the given index, or nil if none exists.
func (c *Caps) GetStructureAt(idx int) *Structure {
st := C.gst_caps_get_structure(c.Instance(), C.guint(idx))
if st == nil {
return nil
}
return wrapStructure(st)
}
// GetFeaturesAt returns the feature at the given index, or nil if none exists.
func (c *Caps) GetFeaturesAt(idx int) *CapsFeatures {
feats := C.gst_caps_get_features(c.Instance(), C.guint(idx))
if feats == nil {
return nil
}
return wrapCapsFeatures(feats)
}
// CapsIntersectMode represents the modes of caps intersection.
// See the official documentation for more details:
// https://gstreamer.freedesktop.org/documentation/gstreamer/gstcaps.html?gi-language=c#GstCapsIntersectMode
type CapsIntersectMode int
// Type castings of intersect modes
const (
CapsIntersectZigZag CapsIntersectMode = C.GST_CAPS_INTERSECT_ZIG_ZAG
CapsIntersectFirst CapsIntersectMode = C.GST_CAPS_INTERSECT_FIRST
)
// Intersect creates a new Caps that contains all the formats that are common to both these caps and those given.
// Defaults to CapsIntersectZigZag mode.
func (c *Caps) Intersect(caps *Caps) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_intersect(c.Instance(), caps.Instance())))
}
// IntersectFull creates a new Caps that contains all the formats that are common to both these caps those given.
// The order is defined by the CapsIntersectMode used.
func (c *Caps) IntersectFull(caps *Caps, mode CapsIntersectMode) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_intersect_full(c.Instance(), caps.Instance(), C.GstCapsIntersectMode(mode))))
}
// IsAlwaysCompatible returns if this structure is always compatible with another if every media format that is in
// the first is also contained in the second. That is, these caps are a subset of those given.
func (c *Caps) IsAlwaysCompatible(caps *Caps) bool {
return gobool(C.gst_caps_is_always_compatible(c.Instance(), caps.Instance()))
}
// IsAny returns true if these caps match any media format.
func (c *Caps) IsAny() bool { return gobool(C.gst_caps_is_any(c.Instance())) }
// IsEmpty returns true if these caps are empty.
func (c *Caps) IsEmpty() bool { return gobool(C.gst_caps_is_empty(c.Instance())) }
// IsEqual returns true if the caps given represent the same set as these.
func (c *Caps) IsEqual(caps *Caps) bool {
return gobool(C.gst_caps_is_equal(c.Instance(), caps.Instance()))
}
// IsEqualFixed tests if the Caps are equal. This function only works on fixed Caps.
func (c *Caps) IsEqualFixed(caps *Caps) bool {
return gobool(C.gst_caps_is_equal_fixed(c.Instance(), caps.Instance()))
}
// IsFixed returns true if these caps are fixed, that is, they describe exactly one format.
func (c *Caps) IsFixed() bool { return gobool(C.gst_caps_is_fixed(c.Instance())) }
// IsStrictlyEqual checks if the given caps are exactly the same set of caps.
func (c *Caps) IsStrictlyEqual(caps *Caps) bool {
return gobool(C.gst_caps_is_strictly_equal(c.Instance(), caps.Instance()))
}
// IsSubset checks if all caps represented by these are also represented by those given.
func (c *Caps) IsSubset(caps *Caps) bool {
return gobool(C.gst_caps_is_subset(c.Instance(), caps.Instance()))
}
// IsSubsetStructure checks if the given structure is a subset of these caps.
func (c *Caps) IsSubsetStructure(structure *Structure) bool {
return gobool(C.gst_caps_is_subset_structure(c.Instance(), structure.Instance()))
}
// IsSubsetStructureFull checks if the given structure is a subset of these caps with features.
func (c *Caps) IsSubsetStructureFull(structure *Structure, features *CapsFeatures) bool {
if features == nil {
return gobool(C.gst_caps_is_subset_structure_full(
c.Instance(), structure.Instance(), nil,
))
}
return gobool(C.gst_caps_is_subset_structure_full(
c.Instance(), structure.Instance(), features.Instance(),
))
}
// IsWritable returns true if these caps are writable.
func (c *Caps) IsWritable() bool {
return gobool(C.capsIsWritable(c.Instance()))
}
// MapInPlace calls the provided function once for each structure and caps feature in the Caps.
// In contrast to ForEach, the function may modify, but not delete, the structures and features.
// The caps must be mutable.
func (c *Caps) MapInPlace(f CapsMapFunc) bool {
ptr := gopointer.Save(f)
defer gopointer.Unref(ptr)
return gobool(C.gst_caps_map_in_place(
c.Instance(),
C.GstCapsMapFunc(C.cgoCapsMapFunc),
(C.gpointer)(ptr),
))
}
// Merge appends the structures contained in the given caps if they are not yet expressed by these.
// The structures in the given caps are not copied -- they are transferred to a writable copy of these ones,
// and then those given are freed. If either caps are ANY, the resulting caps will be ANY.
func (c *Caps) Merge(caps *Caps) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_merge(c.Ref().Instance(), caps.Ref().Instance())))
}
// MergeStructure appends structure to caps if its not already expressed by caps.
func (c *Caps) MergeStructure(structure *Structure) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_merge_structure(c.Ref().Instance(), structure.Instance())))
}
// MergeStructureFull appends structure with features to the caps if its not already expressed.
func (c *Caps) MergeStructureFull(structure *Structure, features *CapsFeatures) *Caps {
if features == nil {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_merge_structure_full(
c.Ref().Instance(), structure.Instance(), nil,
)))
}
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_merge_structure_full(
c.Ref().Instance(), structure.Instance(), features.Instance(),
)))
}
// Normalize returns a Caps that represents the same set of formats as caps, but contains no lists.
// Each list is expanded into separate GstStructures.
//
// This function takes ownership of caps and will call MakeWritable on it so you must not
// use caps afterwards unless you keep an additional reference to it with Ref.
func (c *Caps) Normalize() *Caps {
return wrapCaps(C.gst_caps_normalize(c.Instance()))
}
// RemoveStructureAt removes the structure with the given index from the list of structures.
func (c *Caps) RemoveStructureAt(idx uint) {
C.gst_caps_remove_structure(c.Instance(), C.guint(idx))
}
// SetFeaturesAt sets the CapsFeatures features for the structure at index.
func (c *Caps) SetFeaturesAt(idx uint, features *CapsFeatures) {
if features == nil {
C.gst_caps_set_features(c.Instance(), C.guint(idx), nil)
return
}
C.gst_caps_set_features(c.Instance(), C.guint(idx), features.Instance())
}
// SetFeaturesSimple sets the CapsFeatures for all the structures of these caps.
func (c *Caps) SetFeaturesSimple(features *CapsFeatures) {
if features == nil {
C.gst_caps_set_features_simple(c.Instance(), nil)
return
}
C.gst_caps_set_features_simple(c.Instance(), features.Instance())
}
// SetValue sets the given field on all structures of caps to the given value. This is a convenience
// function for calling SetValue on all structures of caps. If the value cannot be coerced to a C type,
// then nothing will happen.
func (c *Caps) SetValue(field string, val interface{}) {
gVal, err := glib.GValue(val)
if err != nil {
return
}
C.gst_caps_set_value(
c.Instance(),
(*C.gchar)(unsafe.Pointer(C.CString(field))),
(*C.GValue)(unsafe.Pointer(gVal.GValue)),
)
}
// Simplify converts the given caps into a representation that represents the same set of formats, but in a
// simpler form. Component structures that are identical are merged. Component structures that have values
// that can be merged are also merged.
//
// This function takes ownership of caps and will call MakeWritable on it if necessary, so you must not use
// caps afterwards unless you keep an additional reference to it with Ref.
//
// This method does not preserve the original order of caps.
func (c *Caps) Simplify() *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_simplify(c.Ref().Instance())))
}
// StealStructureAt retrieves the structure with the given index from the list of structures contained in caps.
// The caller becomes the owner of the returned structure.
func (c *Caps) StealStructureAt(idx uint) *Structure {
return wrapStructure(C.gst_caps_steal_structure(c.Instance(), C.guint(idx)))
}
// Subtract subtracts the given caps from these.
func (c *Caps) Subtract(caps *Caps) *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_subtract(c.Instance(), caps.Instance())))
}
// Truncate discards all but the first structure from caps. Useful when fixating.
//
// This function takes ownership of caps and will call gst_caps_make_writable on it if necessary, so you must not
// use caps afterwards unless you keep an additional reference to it with Ref.
//
// Note that it is not guaranteed that the returned caps have exactly one structure. If caps is any or empty caps
// then then returned caps will be the same and contain no structure at all.
func (c *Caps) Truncate() *Caps {
return FromGstCapsUnsafeFull(unsafe.Pointer(C.gst_caps_truncate(c.Ref().Instance())))
}