/
gst_element_factory.go
148 lines (122 loc) · 4.96 KB
/
gst_element_factory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package gst
// #include "gst.go.h"
import "C"
import (
"fmt"
"runtime"
"unsafe"
"github.com/go-gst/go-glib/glib"
)
// NewElement creates a new element using the factory of the given name.
func NewElement(factory string) (*Element, error) {
return NewElementWithName(factory, "")
}
// NewElementWithName creates a new element and sets it's name to the given value.
func NewElementWithName(factory string, name string) (*Element, error) {
elemName := C.CString(factory)
defer C.free(unsafe.Pointer(elemName))
var elem *C.GstElement
if name == "" {
elem = C.gst_element_factory_make((*C.gchar)(elemName), nil)
} else {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
elem = C.gst_element_factory_make((*C.gchar)(elemName), (*C.gchar)(cname))
}
if elem == nil {
return nil, fmt.Errorf("could not create element: %s", factory)
}
return wrapElement(glib.TransferNone(unsafe.Pointer(elem))), nil
}
// Create a new element of the type defined by the given elementfactory. The supplied list of properties, will be passed at object construction.
//
// this function is needed for gstreamer props that have the "Construct Only" flag, e.g.:
// https://gstreamer.freedesktop.org/documentation/audio/gstaudioaggregator.html?gi-language=c#GstAudioAggregator:force-live
func NewElementWithProperties(factory string, properties map[string]interface{}) (*Element, error) {
props := make([]*C.char, 0)
values := make([]C.GValue, 0)
for p, v := range properties {
cpropName := C.CString(p)
defer C.free(unsafe.Pointer(cpropName))
props = append(props, cpropName)
value, err := glib.GValue(v)
if err != nil {
return nil, err
}
// value goes out of scope, but the finalizer must not run until the cgo call is finished
defer runtime.KeepAlive(value)
values = append(values, *(*C.GValue)(value.Unsafe()))
}
cfactory := C.CString(factory)
defer C.free(unsafe.Pointer(cfactory))
n := C.uint(len(properties))
p := unsafe.SliceData(props)
v := unsafe.SliceData(values)
elem := C.gst_element_factory_make_with_properties(cfactory, n, p, v)
if elem == nil {
return nil, fmt.Errorf("could not create element: %s", factory)
}
return wrapElement(glib.TransferNone(unsafe.Pointer(elem))), nil
}
// NewElementMany is a convenience wrapper around building many GstElements in a
// single function call. It returns an error if the creation of any element fails. A
// slice in the order the names were given is returned.
func NewElementMany(elemNames ...string) ([]*Element, error) {
elems := make([]*Element, len(elemNames))
for idx, name := range elemNames {
elem, err := NewElement(name)
if err != nil {
return nil, err
}
elems[idx] = elem
}
return elems, nil
}
// ElementFactory wraps the GstElementFactory
type ElementFactory struct{ *PluginFeature }
// Find returns the factory for the given plugin, or nil if it doesn't exist. Unref after usage.
func Find(name string) *ElementFactory {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
factory := C.gst_element_factory_find((*C.gchar)(cName))
if factory == nil {
return nil
}
return wrapElementFactory(glib.TransferFull(unsafe.Pointer(factory)))
}
// Instance returns the C GstFactory instance
func (e *ElementFactory) Instance() *C.GstElementFactory { return C.toGstElementFactory(e.Unsafe()) }
// CanSinkAllCaps checks if the factory can sink all possible capabilities.
func (e *ElementFactory) CanSinkAllCaps(caps *Caps) bool {
return gobool(C.gst_element_factory_can_sink_all_caps((*C.GstElementFactory)(e.Instance()), (*C.GstCaps)(caps.Instance())))
}
// CanSinkAnyCaps checks if the factory can sink any possible capability.
func (e *ElementFactory) CanSinkAnyCaps(caps *Caps) bool {
return gobool(C.gst_element_factory_can_sink_any_caps((*C.GstElementFactory)(e.Instance()), (*C.GstCaps)(caps.Instance())))
}
// CanSourceAllCaps checks if the factory can src all possible capabilities.
func (e *ElementFactory) CanSourceAllCaps(caps *Caps) bool {
return gobool(C.gst_element_factory_can_src_all_caps((*C.GstElementFactory)(e.Instance()), (*C.GstCaps)(caps.Instance())))
}
// CanSourceAnyCaps checks if the factory can src any possible capability.
func (e *ElementFactory) CanSourceAnyCaps(caps *Caps) bool {
return gobool(C.gst_element_factory_can_src_any_caps((*C.GstElementFactory)(e.Instance()), (*C.GstCaps)(caps.Instance())))
}
// GetMetadata gets the metadata on this factory with key.
func (e *ElementFactory) GetMetadata(key string) string {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
res := C.gst_element_factory_get_metadata((*C.GstElementFactory)(e.Instance()), (*C.gchar)(ckey))
defer C.free(unsafe.Pointer(res))
return C.GoString(res)
}
// GetMetadataKeys gets the available keys for the metadata on this factory.
func (e *ElementFactory) GetMetadataKeys() []string {
keys := C.gst_element_factory_get_metadata_keys((*C.GstElementFactory)(e.Instance()))
if keys == nil {
return nil
}
defer C.g_strfreev(keys)
size := C.sizeOfGCharArray(keys)
return goStrings(size, keys)
}