mirror of
https://github.com/go-gst/go-gst.git
synced 2025-09-26 20:11:18 +08:00
567 lines
23 KiB
Go
567 lines
23 KiB
Go
package gst
|
|
|
|
/*
|
|
#include "gst.go.h"
|
|
|
|
extern void goGDestroyNotifyFuncNoRun (gpointer user_data);
|
|
extern void goElementCallAsync (GstElement * element, gpointer user_data);
|
|
|
|
void cgoElementAsyncDestroyNotify (gpointer user_data)
|
|
{
|
|
goGDestroyNotifyFuncNoRun(user_data);
|
|
}
|
|
|
|
void cgoElementCallAsync (GstElement * element, gpointer user_data)
|
|
{
|
|
goElementCallAsync(element, user_data);
|
|
}
|
|
|
|
gboolean elementParentPostMessage (GstElement * element, GstMessage * message) {
|
|
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(element));
|
|
GstElementClass * parent = toGstElementClass(g_type_class_peek_parent(this_class));
|
|
return parent->post_message(element, message);
|
|
}
|
|
|
|
GstStateChangeReturn elementParentChangeState (GstElement * element, GstStateChange transition)
|
|
{
|
|
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(element));
|
|
GstElementClass * parent = toGstElementClass(g_type_class_peek_parent(this_class));
|
|
return parent->change_state(element, transition);
|
|
}
|
|
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"runtime"
|
|
"unsafe"
|
|
|
|
"github.com/go-gst/go-glib/glib"
|
|
gopointer "github.com/mattn/go-pointer"
|
|
)
|
|
|
|
// Element is a Go wrapper around a GstElement.
|
|
type Element struct{ *Object }
|
|
|
|
// FromGstElementUnsafeNone wraps the given element with a ref and a finalizer.
|
|
func FromGstElementUnsafeNone(elem unsafe.Pointer) *Element {
|
|
if elem == nil {
|
|
return nil
|
|
}
|
|
return &Element{Object: &Object{InitiallyUnowned: &glib.InitiallyUnowned{Object: glib.TransferNone(elem)}}}
|
|
}
|
|
|
|
// FromGstElementUnsafeFull wraps the given element with a finalizer.
|
|
func FromGstElementUnsafeFull(elem unsafe.Pointer) *Element {
|
|
if elem == nil {
|
|
return nil
|
|
}
|
|
return &Element{Object: &Object{InitiallyUnowned: &glib.InitiallyUnowned{Object: glib.TransferFull(elem)}}}
|
|
}
|
|
|
|
// ToElement returns an Element object for the given Object. It will work
|
|
// on either gst.Object or glib.Object interfaces.
|
|
func ToElement(obj interface{}) *Element {
|
|
switch obj := obj.(type) {
|
|
case *Object:
|
|
return &Element{Object: obj}
|
|
case *glib.Object:
|
|
return &Element{Object: &Object{InitiallyUnowned: &glib.InitiallyUnowned{Object: obj}}}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ElementLinkMany is a go implementation of `gst_element_link_many` to compensate for
|
|
// no variadic functions in cgo.
|
|
func ElementLinkMany(elems ...*Element) error {
|
|
for idx, elem := range elems {
|
|
if idx == 0 {
|
|
// skip the first one as the loop always links previous to current
|
|
continue
|
|
}
|
|
if err := elems[idx-1].Link(elem); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ElementUnlinkMany is a go implementation of `gst_element_unlink_many` to compensate for
|
|
// no variadic functions in cgo.
|
|
func ElementUnlinkMany(elems ...*Element) {
|
|
for idx, elem := range elems {
|
|
if idx == 0 {
|
|
// skip the first one as the loop always links previous to current
|
|
continue
|
|
}
|
|
elems[idx-1].Unlink(elem)
|
|
}
|
|
}
|
|
|
|
// RegisterElement creates a new elementfactory capable of instantiating objects of the given GoElement
|
|
// and adds the factory to the plugin. A higher rank means more importance when autoplugging.
|
|
func RegisterElement(plugin *Plugin, name string, rank Rank, elem glib.GoObjectSubclass, extends glib.Extendable, interfaces ...glib.Interface) bool {
|
|
return gobool(C.gst_element_register(
|
|
plugin.Instance(),
|
|
C.CString(name),
|
|
C.guint(rank),
|
|
C.GType(glib.RegisterGoType(name, elem, extends, interfaces...)),
|
|
))
|
|
}
|
|
|
|
// Instance returns the underlying GstElement instance.
|
|
func (e *Element) Instance() *C.GstElement { return C.toGstElement(e.Unsafe()) }
|
|
|
|
// AbortState aborts the state change of the element. This function is used by elements that do asynchronous state changes
|
|
// and find out something is wrong.
|
|
func (e *Element) AbortState() { C.gst_element_abort_state(e.Instance()) }
|
|
|
|
// AddPad adds a pad (link point) to element. pad's parent will be set to element
|
|
//
|
|
// Pads are automatically activated when added in the PAUSED or PLAYING state.
|
|
//
|
|
// The pad and the element should be unlocked when calling this function.
|
|
//
|
|
// This function will emit the pad-added signal on the element.
|
|
func (e *Element) AddPad(pad *Pad) bool {
|
|
return gobool(C.gst_element_add_pad(e.Instance(), pad.Instance()))
|
|
}
|
|
|
|
// BlockSetState is like SetState except it will block until the transition
|
|
// is complete.
|
|
func (e *Element) BlockSetState(state State) error {
|
|
if err := e.SetState(state); err != nil {
|
|
return err
|
|
}
|
|
cState := C.GstState(state)
|
|
var curState C.GstState
|
|
C.gst_element_get_state(
|
|
(*C.GstElement)(e.Instance()),
|
|
(*C.GstState)(unsafe.Pointer(&curState)),
|
|
(*C.GstState)(unsafe.Pointer(&cState)),
|
|
C.GstClockTime(ClockTimeNone),
|
|
)
|
|
return nil
|
|
}
|
|
|
|
// CallAsync calls f from another thread. This is to be used for cases when a state change has to be performed from a streaming
|
|
// thread, directly via SetState or indirectly e.g. via SEEK events.
|
|
//
|
|
// Calling those functions directly from the streaming thread will cause deadlocks in many situations, as they might involve waiting
|
|
// for the streaming thread to shut down from this very streaming thread.
|
|
func (e *Element) CallAsync(f func()) {
|
|
ptr := gopointer.Save(f)
|
|
C.gst_element_call_async(
|
|
e.Instance(),
|
|
C.GstElementCallAsyncFunc(C.cgoElementCallAsync),
|
|
(C.gpointer)(unsafe.Pointer(ptr)),
|
|
C.GDestroyNotify(C.cgoElementAsyncDestroyNotify),
|
|
)
|
|
}
|
|
|
|
// ChangeState performs the given transition on this element.
|
|
func (e *Element) ChangeState(transition StateChange) StateChangeReturn {
|
|
return StateChangeReturn(C.gst_element_change_state(e.Instance(), C.GstStateChange(transition)))
|
|
}
|
|
|
|
// Connect connects to the given signal on this element, and applies f as the callback. The callback must
|
|
// match the signature of the expected callback from the documentation. However, instead of specifying C types
|
|
// for arguments specify the go-gst equivalent (e.g. *gst.Element for almost all GstElement derivatives).
|
|
//
|
|
// This and the Emit() method may get moved down the hierarchy to the Object level at some point, since
|
|
func (e *Element) Connect(signal string, f interface{}) (glib.SignalHandle, error) {
|
|
// Elements are sometimes their own type unique from TYPE_ELEMENT. So make sure a type marshaler
|
|
// is registered for whatever this type is. Use the built-in element marshaler.
|
|
if e.TypeFromInstance() != glib.Type(C.GST_TYPE_ELEMENT) {
|
|
glib.RegisterGValueMarshalers([]glib.TypeMarshaler{{T: e.TypeFromInstance(), F: marshalElement}})
|
|
}
|
|
return e.Object.Connect(signal, f, nil)
|
|
}
|
|
|
|
// ContinueState commits the state change of the element and proceed to the next pending state if any. This
|
|
// function is used by elements that do asynchronous state changes. The core will normally call this method
|
|
// automatically when an element returned GST_STATE_CHANGE_SUCCESS from the state change function.
|
|
//
|
|
// If after calling this method the element still has not reached the pending state, the next state change is performed.
|
|
//
|
|
// This method is used internally and should normally not be called by plugins or applications.
|
|
//
|
|
// This function must be called with STATE_LOCK held.
|
|
func (e *Element) ContinueState(ret StateChangeReturn) StateChangeReturn {
|
|
return StateChangeReturn(C.gst_element_continue_state(e.Instance(), C.GstStateChangeReturn(ret)))
|
|
}
|
|
|
|
// Emit is a wrapper around g_signal_emitv() and emits the signal specified by the string s to an Object. Arguments to
|
|
// callback functions connected to this signal must be specified in args. Emit() returns an interface{} which must be
|
|
// type asserted as the Go equivalent type to the return value for native C callback.
|
|
//
|
|
// Note that this code is unsafe in that the types of values in args are not checked against whether they are suitable
|
|
// for the callback.
|
|
func (e *Element) Emit(signal string, args ...interface{}) (interface{}, error) {
|
|
// We are wrapping this for the same reason as Connect.
|
|
if e.TypeFromInstance() != glib.Type(C.GST_TYPE_ELEMENT) {
|
|
glib.RegisterGValueMarshalers([]glib.TypeMarshaler{{T: e.TypeFromInstance(), F: marshalElement}})
|
|
}
|
|
return e.Object.Emit(signal, args...)
|
|
}
|
|
|
|
// InfoMessage is a convenience wrapper for posting an info message from inside an element. Only to be used from
|
|
// plugins.
|
|
func (e *Element) InfoMessage(domain Domain, text string) {
|
|
function, file, line, _ := runtime.Caller(1)
|
|
e.MessageFull(MessageInfo, domain, ErrorCode(0), "", text, path.Base(file), runtime.FuncForPC(function).Name(), line)
|
|
}
|
|
|
|
// WarningMessage is a convenience wrapper for posting a warning message from inside an element. Only to be used from
|
|
// plugins.
|
|
func (e *Element) WarningMessage(domain Domain, text string) {
|
|
function, file, line, _ := runtime.Caller(1)
|
|
e.MessageFull(MessageWarning, domain, ErrorCode(0), "", text, path.Base(file), runtime.FuncForPC(function).Name(), line)
|
|
}
|
|
|
|
// Error is a convenience wrapper around ErrorMessage to simply post the provided go error on the bus.
|
|
// The domain is assumed to be DomainLibrary and the code is assumed to be LibraryErrorFailed.
|
|
func (e *Element) Error(msg string, err error) {
|
|
function, file, line, _ := runtime.Caller(1)
|
|
debugMsg := fmt.Sprintf("%s: %s", msg, err.Error())
|
|
e.MessageFull(MessageError, DomainLibrary, LibraryErrorFailed, err.Error(), debugMsg, path.Base(file), runtime.FuncForPC(function).Name(), line)
|
|
}
|
|
|
|
// ErrorMessage is a convenience wrapper for posting an error message from inside an element. Only to be used from
|
|
// plugins.
|
|
func (e *Element) ErrorMessage(domain Domain, code ErrorCode, text, debug string) {
|
|
function, file, line, _ := runtime.Caller(1)
|
|
e.MessageFull(MessageError, domain, code, text, debug, path.Base(file), runtime.FuncForPC(function).Name(), line)
|
|
}
|
|
|
|
// MessageFull will post an error, warning, or info message on the bus from inside an element. Only to be used
|
|
// from plugins.
|
|
func (e *Element) MessageFull(msgType MessageType, domain Domain, code ErrorCode, text, debug, file, function string, line int) {
|
|
var cTxt, cDbg unsafe.Pointer = nil, nil
|
|
if text != "" {
|
|
ctxtstr := C.CString(debug)
|
|
defer C.free(unsafe.Pointer(ctxtstr))
|
|
cTxt = unsafe.Pointer(C.g_strdup((*C.gchar)(unsafe.Pointer(ctxtstr))))
|
|
}
|
|
if debug != "" {
|
|
cdbgstr := C.CString(debug)
|
|
defer C.free(unsafe.Pointer(cdbgstr))
|
|
cDbg = unsafe.Pointer(C.g_strdup((*C.gchar)(unsafe.Pointer(cdbgstr))))
|
|
}
|
|
C.gst_element_message_full(
|
|
e.Instance(),
|
|
C.GstMessageType(msgType),
|
|
domain.toQuark(),
|
|
C.gint(code),
|
|
(*C.gchar)(cTxt),
|
|
(*C.gchar)(cDbg),
|
|
C.CString(file),
|
|
C.CString(function),
|
|
C.gint(line),
|
|
)
|
|
}
|
|
|
|
// GetBus returns the GstBus for retrieving messages from this element. This function returns
|
|
// nil unless the element is a Pipeline.
|
|
func (e *Element) GetBus() *Bus {
|
|
bus := C.gst_element_get_bus((*C.GstElement)(e.Instance()))
|
|
if bus == nil {
|
|
return nil
|
|
}
|
|
return FromGstBusUnsafeFull(unsafe.Pointer(bus))
|
|
}
|
|
|
|
// GetClock returns the Clock for this element. This is the clock as was last set with gst_element_set_clock.
|
|
// Elements in a pipeline will only have their clock set when the pipeline is in the PLAYING state.
|
|
func (e *Element) GetClock() *Clock {
|
|
cClock := C.gst_element_get_clock((*C.GstElement)(e.Instance()))
|
|
if cClock == nil {
|
|
return nil
|
|
}
|
|
return FromGstClockUnsafeFull(unsafe.Pointer(cClock))
|
|
}
|
|
|
|
// GetFactory returns the factory that created this element. No refcounting is needed.
|
|
func (e *Element) GetFactory() *ElementFactory {
|
|
factory := C.gst_element_get_factory((*C.GstElement)(e.Instance()))
|
|
if factory == nil {
|
|
return nil
|
|
}
|
|
return wrapElementFactory(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(factory))})
|
|
}
|
|
|
|
// GetPads retrieves a list of pads associated with the element.
|
|
func (e *Element) GetPads() ([]*Pad, error) {
|
|
iter := C.gst_element_iterate_pads(e.Instance())
|
|
if iter == nil {
|
|
return nil, nil
|
|
}
|
|
return iteratorToPadSlice(iter)
|
|
}
|
|
|
|
// GetSinkPads retrieves a list of sink pads associated with the element.
|
|
func (e *Element) GetSinkPads() ([]*Pad, error) {
|
|
iter := C.gst_element_iterate_sink_pads(e.Instance())
|
|
if iter == nil {
|
|
return nil, nil
|
|
}
|
|
return iteratorToPadSlice(iter)
|
|
}
|
|
|
|
// GetSrcPads retrieves a list of src pads associated with the element.
|
|
func (e *Element) GetSrcPads() ([]*Pad, error) {
|
|
iter := C.gst_element_iterate_src_pads(e.Instance())
|
|
if iter == nil {
|
|
return nil, nil
|
|
}
|
|
return iteratorToPadSlice(iter)
|
|
}
|
|
|
|
// GetPadTemplates retrieves a list of the pad templates associated with this element.
|
|
// The list must not be modified by the calling code.
|
|
func (e *Element) GetPadTemplates() []*PadTemplate {
|
|
glist := C.gst_element_get_pad_template_list((*C.GstElement)(e.Instance()))
|
|
if glist == nil {
|
|
return nil
|
|
}
|
|
goList := glib.WrapList(uintptr(unsafe.Pointer(glist)))
|
|
out := make([]*PadTemplate, 0)
|
|
goList.Foreach(func(item interface{}) {
|
|
pt := item.(unsafe.Pointer)
|
|
out = append(out, wrapPadTemplate(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(pt))}))
|
|
})
|
|
return out
|
|
}
|
|
|
|
// GetState returns the current state of this element.
|
|
func (e *Element) GetState() State {
|
|
return State(e.Instance().current_state)
|
|
}
|
|
|
|
// GetStaticPad retrieves a pad from element by name. This version only retrieves
|
|
// already-existing (i.e. 'static') pads.
|
|
func (e *Element) GetStaticPad(name string) *Pad {
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
pad := C.gst_element_get_static_pad(e.Instance(), (*C.gchar)(unsafe.Pointer(cname)))
|
|
if pad == nil {
|
|
return nil
|
|
}
|
|
return FromGstPadUnsafeFull(unsafe.Pointer(pad))
|
|
}
|
|
|
|
// Has returns true if this element has the given flags.
|
|
func (e *Element) Has(flags ElementFlags) bool {
|
|
return gobool(C.gstObjectFlagIsSet(C.toGstObject(e.Unsafe()), C.GstElementFlags(flags)))
|
|
}
|
|
|
|
// IsURIHandler returns true if this element can handle URIs.
|
|
func (e *Element) IsURIHandler() bool {
|
|
return gobool(C.gstElementIsURIHandler(e.Instance()))
|
|
}
|
|
|
|
// Link wraps gst_element_link and links this element to the given one.
|
|
func (e *Element) Link(elem *Element) error {
|
|
if ok := C.gst_element_link((*C.GstElement)(e.Instance()), (*C.GstElement)(elem.Instance())); !gobool(ok) {
|
|
return fmt.Errorf("failed to link %s to %s", e.GetName(), elem.GetName())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e *Element) Unlink(elem *Element) {
|
|
C.gst_element_unlink((*C.GstElement)(e.Instance()), (*C.GstElement)(elem.Instance()))
|
|
}
|
|
|
|
// LinkFiltered wraps gst_element_link_filtered and link this element to the given one
|
|
// using the provided sink caps.
|
|
func (e *Element) LinkFiltered(elem *Element, filter *Caps) error {
|
|
if filter == nil {
|
|
if ok := C.gst_element_link_filtered(e.Instance(), elem.Instance(), nil); !gobool(ok) {
|
|
return fmt.Errorf("failed to link %s to %s with provided caps", e.GetName(), elem.GetName())
|
|
}
|
|
return nil
|
|
}
|
|
if ok := C.gst_element_link_filtered(e.Instance(), elem.Instance(), filter.Instance()); !gobool(ok) {
|
|
return fmt.Errorf("failed to link %s to %s with provided caps", e.GetName(), elem.GetName())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ParentChangeState can be used when extending an element to chain up to the parents ChangeState
|
|
// handler.
|
|
func (e *Element) ParentChangeState(transition StateChange) StateChangeReturn {
|
|
return StateChangeReturn(C.elementParentChangeState(e.Instance(), C.GstStateChange(transition)))
|
|
}
|
|
|
|
// ParentPostMessage can be used when extending an element. During a PostMessage, use this method
|
|
// to have the message posted on the bus after processing.
|
|
func (e *Element) ParentPostMessage(msg *Message) bool {
|
|
return gobool(C.elementParentPostMessage(e.Instance(), msg.Instance()))
|
|
}
|
|
|
|
// Query performs a query on the given element.
|
|
//
|
|
// For elements that don't implement a query handler, this function forwards the query to a random srcpad or
|
|
// to the peer of a random linked sinkpad of this element.
|
|
//
|
|
// Please note that some queries might need a running pipeline to work.
|
|
func (e *Element) Query(q *Query) bool {
|
|
return gobool(C.gst_element_query(e.Instance(), q.Instance()))
|
|
}
|
|
|
|
// QueryConvert queries an element to convert src_val in src_format to dest_format.
|
|
func (e *Element) QueryConvert(srcFormat Format, srcValue int64, destFormat Format) (bool, int64) {
|
|
var out C.gint64
|
|
gok := C.gst_element_query_convert(e.Instance(), C.GstFormat(srcFormat), C.gint64(srcValue), C.GstFormat(destFormat), &out)
|
|
return gobool(gok), int64(out)
|
|
}
|
|
|
|
// QueryDuration queries an element (usually top-level pipeline or playbin element) for the total stream
|
|
// duration in nanoseconds. This query will only work once the pipeline is prerolled (i.e. reached PAUSED
|
|
// or PLAYING state). The application will receive an ASYNC_DONE message on the pipeline bus when that is
|
|
// the case.
|
|
//
|
|
// If the duration changes for some reason, you will get a DURATION_CHANGED message on the pipeline bus,
|
|
// in which case you should re-query the duration using this function.
|
|
func (e *Element) QueryDuration(format Format) (bool, int64) {
|
|
var out C.gint64
|
|
gok := C.gst_element_query_duration(e.Instance(), C.GstFormat(format), &out)
|
|
return gobool(gok), int64(out)
|
|
}
|
|
|
|
// QueryPosition queries an element (usually top-level pipeline or playbin element) for the stream position
|
|
// in nanoseconds. This will be a value between 0 and the stream duration (if the stream duration is known).
|
|
// This query will usually only work once the pipeline is prerolled (i.e. reached PAUSED or PLAYING state).
|
|
// The application will receive an ASYNC_DONE message on the pipeline bus when that is the case.
|
|
func (e *Element) QueryPosition(format Format) (bool, int64) {
|
|
var out C.gint64
|
|
gok := C.gst_element_query_position(e.Instance(), C.GstFormat(format), &out)
|
|
return gobool(gok), int64(out)
|
|
}
|
|
|
|
// SendEvent sends an event to an element. If the element doesn't implement an event handler, the event will
|
|
// be pushed on a random linked sink pad for downstream events or a random linked source pad for upstream events.
|
|
//
|
|
// This function takes ownership of the provided event so you should gst_event_ref it if you want to reuse the event
|
|
// after this call.
|
|
func (e *Element) SendEvent(ev *Event) bool {
|
|
return gobool(C.gst_element_send_event(e.Instance(), ev.Ref().Instance()))
|
|
}
|
|
|
|
// SetState sets the target state for this element.
|
|
func (e *Element) SetState(state State) error {
|
|
stateRet := C.gst_element_set_state((*C.GstElement)(e.Instance()), C.GstState(state))
|
|
if stateRet == C.GST_STATE_CHANGE_FAILURE {
|
|
return fmt.Errorf("failed to change state to %s", state.String())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SyncStateWithParent tries to change the state of the element to the same as its parent. If this function returns
|
|
// FALSE, the state of element is undefined.
|
|
func (e *Element) SyncStateWithParent() bool {
|
|
return gobool(C.gst_element_sync_state_with_parent(e.Instance()))
|
|
}
|
|
|
|
// TOCSetter returns a TOCSetter interface if implemented by this element. Otherwise it
|
|
// returns nil. Currently this only supports elements built through this package, however,
|
|
// inner application elements could still use the interface as a reference implementation.
|
|
func (e *Element) TOCSetter() TOCSetter {
|
|
if C.toTocSetter(e.Instance()) == nil {
|
|
return nil
|
|
}
|
|
return &gstTOCSetter{ptr: e.Instance()}
|
|
}
|
|
|
|
// TagSetter returns a TagSetter interface if implemented by this element. Otherwise it returns nil.
|
|
// This currently only supports elements built through this package's bindings, however, inner application
|
|
// elements can still implement the interface themselves if they want.
|
|
func (e *Element) TagSetter() TagSetter {
|
|
if C.toTagSetter(e.Instance()) == nil {
|
|
return nil
|
|
}
|
|
return &gstTagSetter{ptr: e.Instance()}
|
|
}
|
|
|
|
// URIHandler returns a URIHandler interface if implemented by this element. Otherwise it
|
|
// returns nil. Currently this only supports elements built through this package, however,
|
|
// inner application elements could still use the interface as a reference implementation.
|
|
func (e *Element) URIHandler() URIHandler {
|
|
if C.toGstURIHandler(e.Unsafe()) == nil {
|
|
return nil
|
|
}
|
|
return &gstURIHandler{ptr: e.Instance()}
|
|
}
|
|
|
|
// RemovePad removes pad from element. pad will be destroyed if it has not been referenced elsewhere using gst_object_unparent.
|
|
//
|
|
// This function is used by plugin developers and should not be used by applications. Pads that were dynamically requested from
|
|
// elements with gst_element_request_pad should be released with the gst_element_release_request_pad function instead.
|
|
//
|
|
// Pads are not automatically deactivated so elements should perform the needed steps to deactivate the pad in case this pad is
|
|
// removed in the PAUSED or PLAYING state. See gst_pad_set_active for more information about deactivating pads.
|
|
//
|
|
// The pad and the element should be unlocked when calling this function.
|
|
//
|
|
// This function will emit the pad-removed signal on the element.
|
|
func (e *Element) RemovePad(pad *Pad) bool {
|
|
return gobool(C.gst_element_remove_pad(e.Instance(), pad.Instance()))
|
|
}
|
|
|
|
// GetRequestPad gets a request pad from the element based on the name of the pad template.
|
|
// Unlike static pads, request pads are not created automatically but are only created on demand
|
|
// For example, audiomixer has sink template, 'sink_%u', which is used for creating multiple sink pads on demand so that it performs mixing of audio streams by linking multiple upstream elements on it's sink pads created on demand.
|
|
// This returns the request pad created on demand. Otherwise, it returns null if failed to create.
|
|
func (e *Element) GetRequestPad(name string) *Pad {
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
pad := C.gst_element_get_request_pad(e.Instance(), (*C.gchar)(unsafe.Pointer(cname)))
|
|
if pad == nil {
|
|
return nil
|
|
}
|
|
return FromGstPadUnsafeFull(unsafe.Pointer(pad))
|
|
}
|
|
|
|
// ReleaseRequestPad releases request pad
|
|
func (e *Element) ReleaseRequestPad(pad *Pad) {
|
|
C.gst_element_release_request_pad(e.Instance(), pad.Instance())
|
|
}
|
|
|
|
// Set the start time of an element. The start time of the element is the running time of the element
|
|
// when it last went to the PAUSED state. In READY or after a flushing seek, it is set to 0.
|
|
//
|
|
// Toplevel elements like GstPipeline will manage the start_time and base_time on its children.
|
|
// Setting the start_time to GST_CLOCK_TIME_NONE on such a toplevel element will disable the distribution of the base_time
|
|
// to the children and can be useful if the application manages the base_time itself, for example if you want to synchronize
|
|
// capture from multiple pipelines, and you can also ensure that the pipelines have the same clock.
|
|
//
|
|
// MT safe.
|
|
func (e *Element) SetStartTime(startTime ClockTime) {
|
|
C.gst_element_set_start_time(e.Instance(), C.GstClockTime(startTime))
|
|
}
|
|
|
|
// Returns the start time of the element. The start time is the running time of the clock when this element was last put to PAUSED.
|
|
// Usually the start_time is managed by a toplevel element such as GstPipeline.
|
|
// MT safe.
|
|
func (e *Element) GetStartTime() ClockTime {
|
|
ctime := C.gst_element_get_start_time(e.Instance())
|
|
|
|
return ClockTime(ctime)
|
|
}
|
|
|
|
// Set the base time of an element. The base time is the absolute time of the clock
|
|
// when this element was last put to PLAYING. Subtracting the base time from the clock time gives the running time of the element.
|
|
func (e *Element) SetBaseTime(startTime ClockTime) {
|
|
C.gst_element_set_base_time(e.Instance(), C.GstClockTime(startTime))
|
|
}
|
|
|
|
// Returns the base time of the element. The base time is the absolute time of the clock
|
|
// when this element was last put to PLAYING. Subtracting the base time from the clock time gives the running time of the element.
|
|
func (e *Element) GetBaseTime() ClockTime {
|
|
ctime := C.gst_element_get_base_time(e.Instance())
|
|
|
|
return ClockTime(ctime)
|
|
}
|