mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-04 07:36:41 +08:00
488 lines
18 KiB
Go
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())))
|
|
}
|