halfway done with GstPad impl

This commit is contained in:
tinyzimmer
2020-10-03 09:44:47 +03:00
parent 79854aeba2
commit 02fa43822c
5 changed files with 378 additions and 57 deletions

View File

@@ -11,6 +11,10 @@ import (
"github.com/gotk3/gotk3/glib"
)
func toGObject(data unsafe.Pointer) *glib.Object {
return &glib.Object{GObject: glib.ToGObject(data)}
}
// gobool provides an easy type conversion between C.gboolean and a go bool.
func gobool(b C.gboolean) bool {
return int(b) > 0
@@ -103,7 +107,7 @@ func glistToStreamSlice(glist *C.GList) []*Stream {
out := make([]*Stream, 0)
l.FreeFull(func(item interface{}) {
st := item.(*C.GstStream)
out = append(out, wrapStream(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(st))}))
out = append(out, wrapStream(toGObject(unsafe.Pointer(st))))
})
return out
}

View File

@@ -14,51 +14,19 @@ import (
)
//export goPadProbeFunc
func goPadProbeFunc(gstPad *C.GstPad, gstProbeInfo *C.GstPadProbeInfo, userData C.gpointer) C.GstPadProbeReturn {
func goPadProbeFunc(gstPad *C.GstPad, info *C.GstPadProbeInfo, userData C.gpointer) C.GstPadProbeReturn {
cbIface := gopointer.Restore(unsafe.Pointer(userData))
cbFunc := cbIface.(PadProbeCallback)
pad := wrapPad(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gstPad))})
probeInfo := &PadProbeInfo{
ID: uint32(gstProbeInfo.id),
Type: PadProbeType(gstProbeInfo._type),
Offset: uint64(gstProbeInfo.offset),
Size: uint64(gstProbeInfo.size),
}
populateProbeInfoData(probeInfo, gstProbeInfo.data)
return C.GstPadProbeReturn(cbFunc(pad, probeInfo))
return C.GstPadProbeReturn(cbFunc(pad, &PadProbeInfo{info}))
}
// Figures out what to populate the probe info data with based on the type.
func populateProbeInfoData(probeInfo *PadProbeInfo, data C.gpointer) {
switch probeInfo.Type {
// Buffer
case PadProbeTypeBuffer:
probeInfo.Data = wrapBuffer((*C.GstBuffer)(unsafe.Pointer(data)))
// BufferList
case PadProbeTypeBufferList:
probeInfo.Data = wrapBufferList((*C.GstBufferList)(unsafe.Pointer(data)))
// Events
case PadProbeTypeEventDownstream:
probeInfo.Data = wrapEvent((*C.GstEvent)(unsafe.Pointer(data)))
case PadProbeTypeEventUpstream:
probeInfo.Data = wrapEvent((*C.GstEvent)(unsafe.Pointer(data)))
case PadProbeTypeEventFlush:
probeInfo.Data = wrapEvent((*C.GstEvent)(unsafe.Pointer(data)))
case PadProbeTypeEventBoth:
probeInfo.Data = wrapEvent((*C.GstEvent)(unsafe.Pointer(data)))
// Queries
case PadProbeTypeQueryDownstream:
probeInfo.Data = wrapQuery((*C.GstQuery)(unsafe.Pointer(data)))
case PadProbeTypeQueryUpstream:
probeInfo.Data = wrapQuery((*C.GstQuery)(unsafe.Pointer(data)))
case PadProbeTypeQueryBoth:
probeInfo.Data = wrapQuery((*C.GstQuery)(unsafe.Pointer(data)))
}
//export goPadForwardFunc
func goPadForwardFunc(gpad *C.GstPad, userData C.gpointer) C.gboolean {
cbIface := gopointer.Restore(unsafe.Pointer(userData))
cbFunc := cbIface.(PadForwardFunc)
pad := wrapPad(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gpad))})
return gboolean(cbFunc(pad))
}
//export goTagForEachFunc

View File

@@ -775,6 +775,16 @@ const (
QueryTypeSerialized QueryTypeFlags = C.GST_QUERY_TYPE_SERIALIZED // (4) Set if the query should be serialized with data flow.
)
// TaskState casts GstTaskState
type TaskState int
// Type castings
const (
TaskStarted TaskState = C.GST_TASK_STARTED // (0) the task is started and running
TaskStopped TaskState = C.GST_TASK_STOPPED // (1) the task is stopped
TaskPaused TaskState = C.GST_TASK_PAUSED // (2) the task is paused
)
// TOCScope represents the scope of a TOC.
type TOCScope int

View File

@@ -24,8 +24,11 @@ func (o *Object) Unsafe() unsafe.Pointer {
// Instance returns the native C GstObject.
func (o *Object) Instance() *C.GstObject { return C.toGstObject(o.Unsafe()) }
// Object is an alias to Instance on the underlying GstObject of any extending struct.
func (o *Object) Object() *C.GstObject { return C.toGstObject(o.Unsafe()) }
// BaseObject returns this object for embedding structs.
func (o *Object) BaseObject() *Object { return o }
// GstObject is an alias to Instance on the underlying GstObject of any extending struct.
func (o *Object) GstObject() *C.GstObject { return C.toGstObject(o.Unsafe()) }
// Class returns the GObjectClass of this instance.
func (o *Object) Class() *C.GObjectClass { return C.getGObjectClass(o.Unsafe()) }

View File

@@ -1,12 +1,34 @@
package gst
// #include "gst.go.h"
/*
#include "gst.go.h"
extern GstPadProbeReturn goPadProbeFunc (GstPad * pad, GstPadProbeInfo * info, gpointer user_data);
extern gboolean goPadForwardFunc (GstPad * pad, gpointer user_data);
extern void goGDestroyNotifyFuncNoRun (gpointer user_data);
GstPadProbeReturn cgoPadProbeFunc (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
return goPadProbeFunc(pad, info, user_data);
}
gboolean cgoPadForwardFunc (GstPad * pad, gpointer user_data)
{
return goPadForwardFunc(pad, user_data);
}
void cgoGDestroyNotifyFuncNoRun (gpointer user_data)
{
goGDestroyNotifyFuncNoRun(user_data);
}
*/
import "C"
import (
"unsafe"
"github.com/gotk3/gotk3/glib"
gopointer "github.com/mattn/go-pointer"
)
// Pad is a go representation of a GstPad
@@ -24,7 +46,7 @@ func NewPad(name string, direction PadDirection) *Pad {
if pad == nil {
return nil
}
return wrapPad(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(pad))})
return wrapPad(toGObject(unsafe.Pointer(pad)))
}
// NewPadFromTemplate creates a new pad with the given name from the given template. If name is empty, one will
@@ -40,7 +62,7 @@ func NewPadFromTemplate(tmpl *PadTemplate, name string) *Pad {
if pad == nil {
return nil
}
return wrapPad(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(pad))})
return wrapPad(toGObject(unsafe.Pointer(pad)))
}
// Instance returns the underlying C GstPad.
@@ -53,7 +75,7 @@ func (p *Pad) Direction() PadDirection {
// Template returns the template for this pad or nil.
func (p *Pad) Template() *PadTemplate {
return wrapPadTemplate(glib.Take(unsafe.Pointer(p.Instance().padtemplate)))
return wrapPadTemplate(toGObject(unsafe.Pointer(p.Instance().padtemplate)))
}
// CurrentCaps returns the caps for this Pad or nil.
@@ -73,14 +95,328 @@ func (p *Pad) ActivateMode(mode PadMode, active bool) {
C.gst_pad_activate_mode(p.Instance(), C.GstPadMode(mode), gboolean(active))
}
// PadProbeInfo represents the info passed to a PadProbeCallback.
type PadProbeInfo struct {
ID uint32
Type PadProbeType
// The data in the interface depends on the Type in the probe info
Data interface{}
Offset, Size uint64
}
// PadProbeCallback is a callback used by Pad AddProbe. It gets called to notify about the current blocking type.
type PadProbeCallback func(*Pad, *PadProbeInfo) PadProbeReturn
// AddProbe adds a callback to be notified of different states of pads. The provided callback is called for every state that matches mask.
//
// Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only
// exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called immediately if the pad is already idle while calling gst_pad_add_probe.
// In each of the groups, probes are called in the order in which they were added.
//
// A probe ID is returned that can be used to remove the probe.
func (p *Pad) AddProbe(mask PadProbeType, f PadProbeCallback) uint64 {
ptr := gopointer.Save(f)
ret := C.gst_pad_add_probe(
p.Instance(),
C.GstPadProbeType(mask),
C.GstPadProbeCallback(C.cgoPadProbeFunc),
(C.gpointer)(unsafe.Pointer(ptr)),
C.GDestroyNotify(C.cgoGDestroyNotifyFuncNoRun),
)
return uint64(ret)
}
// CanLink checks if this pad is compatible with the given sink pad.
func (p *Pad) CanLink(sink *Pad) bool {
return gobool(C.gst_pad_can_link(p.Instance(), sink.Instance()))
}
// Chain a buffer to pad.
//
// The function returns FlowFlushing if the pad was flushing.
//
// If the buffer type is not acceptable for pad (as negotiated with a preceding EventCaps event), this function returns FlowNotNegotiated.
//
// The function proceeds calling the chain function installed on pad (see SetChainFunction) and the return value of that function is returned to
// the caller. FlowNotSupported is returned if pad has no chain function.
//
// In all cases, success or failure, the caller loses its reference to buffer after calling this function.
func (p *Pad) Chain(buffer *Buffer) FlowReturn {
return FlowReturn(C.gst_pad_chain(p.Instance(), buffer.Instance()))
}
// ChainList chains a bufferlist to pad.
//
// The function returns FlowFlushing if the pad was flushing.
//
// If pad was not negotiated properly with a CAPS event, this function returns FlowNotNegotiated.
//
// The function proceeds calling the chainlist function installed on pad (see SetChainListFunction) and the return value of that function is returned
// to the caller. FlowNotSupported is returned if pad has no chainlist function.
//
// In all cases, success or failure, the caller loses its reference to list after calling this function.
func (p *Pad) ChainList(bufferList *BufferList) FlowReturn {
return FlowReturn(C.gst_pad_chain_list(p.Instance(), bufferList.Instance()))
}
// CheckReconfigure checks and clear the PadFlagNeedReconfigure flag on pad and return TRUE if the flag was set.
func (p *Pad) CheckReconfigure() bool {
return gobool(C.gst_pad_check_reconfigure(p.Instance()))
}
// CreateStreamID creates a stream-id for the source GstPad pad by combining the upstream information with the optional stream_id of the stream of pad.
// Pad must have a parent GstElement and which must have zero or one sinkpad. stream_id can only be NULL if the parent element of pad has only a single
// source pad.
//
// This function generates an unique stream-id by getting the upstream stream-start event stream ID and appending stream_id to it. If the element has no
// sinkpad it will generate an upstream stream-id by doing an URI query on the element and in the worst case just uses a random number. Source elements
// that don't implement the URI handler interface should ideally generate a unique, deterministic stream-id manually instead.
//
// Since stream IDs are sorted alphabetically, any numbers in the stream ID should be printed with a fixed number of characters, preceded by 0's, such as
// by using the format %03u instead of %u.
func (p *Pad) CreateStreamID(parent *Element, streamID string) string {
var gstreamID *C.gchar
if streamID != "" {
ptr := C.CString(streamID)
defer C.free(unsafe.Pointer(ptr))
gstreamID = (*C.gchar)(unsafe.Pointer(ptr))
}
ret := C.gst_pad_create_stream_id(p.Instance(), parent.Instance(), gstreamID)
if ret == nil {
return ""
}
defer C.g_free((C.gpointer)(unsafe.Pointer(ret)))
return C.GoString(ret)
}
// EventDefault invokes the default event handler for the given pad.
//
// The EOS event will pause the task associated with pad before it is forwarded to all internally linked pads,
//
// The event is sent to all pads internally linked to pad. This function takes ownership of event.
func (p *Pad) EventDefault(parent *Object, event *Event) bool {
return gobool(C.gst_pad_event_default(p.Instance(), parent.Instance(), event.Instance()))
}
// PadForwardFunc is called for all internally linked pads, see Pad Forward().
// If the function returns true, the procedure is stopped.
type PadForwardFunc func(pad *Pad) bool
// Forward calls the given function for all internally linked pads of pad. This function deals with dynamically changing internal pads and will make sure
// that the forward function is only called once for each pad.
//
// When forward returns TRUE, no further pads will be processed.
func (p *Pad) Forward(f PadForwardFunc) bool {
ptr := gopointer.Save(f)
defer gopointer.Unref(ptr)
return gobool(C.gst_pad_forward(
p.Instance(),
C.GstPadForwardFunction(C.cgoPadForwardFunc),
(C.gpointer)(unsafe.Pointer(ptr)),
))
}
// GetAllowedCaps getss the capabilities of the allowed media types that can flow through pad and its peer.
//
// The allowed capabilities is calculated as the intersection of the results of calling QueryCaps on pad and its peer. The caller owns a reference on the
// resulting caps.
func (p *Pad) GetAllowedCaps() *Caps {
return wrapCaps(C.gst_pad_get_allowed_caps(
p.Instance(),
))
}
// GetCurrentCaps gets the capabilities currently configured on pad with the last EventCaps event.
func (p *Pad) GetCurrentCaps() *Caps {
return wrapCaps(C.gst_pad_get_current_caps(
p.Instance(),
))
}
// GetDirection gets the direction of the pad. The direction of the pad is decided at construction time so this function does not take the LOCK.
func (p *Pad) GetDirection() PadDirection {
return PadDirection(C.gst_pad_get_direction(p.Instance()))
}
// GetElementPrivate gets the private data of a pad. No locking is performed in this function.
func (p *Pad) GetElementPrivate() interface{} {
ptr := C.gst_pad_get_element_private(p.Instance())
return gopointer.Restore(unsafe.Pointer(ptr))
}
// GetLastFlowReturn gets the FlowReturn return from the last data passed by this pad.
func (p *Pad) GetLastFlowReturn() FlowReturn {
return FlowReturn(C.gst_pad_get_last_flow_return(
p.Instance(),
))
}
// GetOffset gets the offset applied to the running time of pad. pad has to be a source pad.
func (p *Pad) GetOffset() int64 {
return int64(C.gst_pad_get_offset(p.Instance()))
}
// GetPadTemplate gets the template for this pad.
func (p *Pad) GetPadTemplate() *PadTemplate {
tmpl := C.gst_pad_get_pad_template(p.Instance())
if tmpl == nil {
return nil
}
return wrapPadTemplate(toGObject(unsafe.Pointer(tmpl)))
}
// GetPadTemplateCaps gets the capabilities for pad's template.
func (p *Pad) GetPadTemplateCaps() *Caps {
caps := C.gst_pad_get_pad_template_caps(p.Instance())
if caps == nil {
return nil
}
return wrapCaps(caps)
}
// GetParentElement gets the parent of pad, cast to a Element. If a pad has no parent or its
// parent is not an element, return nil.
func (p *Pad) GetParentElement() *Element {
elem := C.gst_pad_get_parent_element(p.Instance())
if elem == nil {
return nil
}
return wrapElement(toGObject(unsafe.Pointer(elem)))
}
// GetPeer gets the peer of pad. This function refs the peer pad so you need to unref it after use.
func (p *Pad) GetPeer() *Pad {
peer := C.gst_pad_get_peer(p.Instance())
if peer == nil {
return nil
}
return wrapPad(toGObject(unsafe.Pointer(peer)))
}
// GetRange calls the getrange function of pad, see PadGetRangeFunc for a description of a getrange function.
// If pad has no getrange function installed (see SetGetRangeFunction) this function returns FlowNotSupported.
//
// If buffer points to a variable holding nil, a valid new GstBuffer will be placed in buffer when this function
// returns FlowOK. The new buffer must be freed with Unref after usage.
//
// When buffer points to a variable that points to a valid Buffer, the buffer will be filled with the result data
// when this function returns FlowOK. If the provided buffer is larger than size, only size bytes will be filled
// in the result buffer and its size will be updated accordingly.
//
// Note that less than size bytes can be returned in buffer when, for example, an EOS condition is near or when
// buffer is not large enough to hold size bytes. The caller should check the result buffer size to get the result
// size.
//
// When this function returns any other result value than FlowOK, buffer will be unchanged.
//
// This is a lowlevel function. Usually PullRange is used.
func (p *Pad) GetRange(offset uint64, size uint, buffer *Buffer) (FlowReturn, *Buffer) {
var buf *C.GstBuffer
if buffer != nil {
buf = buffer.Instance()
}
ret := C.gst_pad_get_range(p.Instance(), C.guint64(offset), C.guint(size), &buf)
var newBuf *Buffer
if buf != nil {
newBuf = wrapBuffer(buf)
} else {
newBuf = nil
}
return FlowReturn(ret), newBuf
}
// GetSingleInternalLink checks if there is a single internal link of the given pad, and returns it. Otherwise, it will
// return nil.
func (p *Pad) GetSingleInternalLink() *Pad {
pad := C.gst_pad_get_single_internal_link(p.Instance())
if pad == nil {
return nil
}
return wrapPad(toGObject(unsafe.Pointer(pad)))
}
// GetStickyEvent returns a new reference of the sticky event of type event_type from the event.
func (p *Pad) GetStickyEvent(eventType EventType, idx uint) *Event {
ev := C.gst_pad_get_sticky_event(p.Instance(), C.GstEventType(eventType), C.guint(idx))
if ev == nil {
return nil
}
return wrapEvent(ev)
}
// GetStream returns the current Stream for the pad, or nil if none has been set yet, i.e. the pad has not received a
// stream-start event yet.
//
// This is a convenience wrapper around GetStickyEvent and Event ParseStream.
func (p *Pad) GetStream() *Stream {
st := C.gst_pad_get_stream(p.Instance())
if st == nil {
return nil
}
return wrapStream(toGObject(unsafe.Pointer(st)))
}
// GetStreamID returns the current stream-id for the pad, or an empty string if none has been set yet, i.e. the pad has not received
// a stream-start event yet.
//
// This is a convenience wrapper around gst_pad_get_sticky_event and gst_event_parse_stream_start.
//
// The returned stream-id string should be treated as an opaque string, its contents should not be interpreted.
func (p *Pad) GetStreamID() string {
id := C.gst_pad_get_stream_id(p.Instance())
if id == nil {
return ""
}
defer C.g_free((C.gpointer)(unsafe.Pointer(id)))
return C.GoString(id)
}
// GetTaskState gets the pad task state. If no task is currently set, TaskStopped is returned.
func (p *Pad) GetTaskState() TaskState {
return TaskState(C.gst_pad_get_task_state(p.Instance()))
}
// PadProbeInfo represents the info passed to a PadProbeCallback.
type PadProbeInfo struct {
ptr *C.GstPadProbeInfo
}
// ID returns the id of the probe.
func (p *PadProbeInfo) ID() uint32 { return uint32(p.ptr.id) }
// Type returns the type of the probe. The type indicates the type of data that can be expected
// with the probe.
func (p *PadProbeInfo) Type() PadProbeType { return PadProbeType(p.ptr._type) }
// Offset returns the offset of pull probe, this field is valid when type contains PadProbeTypePull.
func (p *PadProbeInfo) Offset() uint64 { return uint64(p.ptr.offset) }
// Size returns the size of pull probe, this field is valid when type contains PadProbeTypePull.
func (p *PadProbeInfo) Size() uint64 { return uint64(p.ptr.size) }
// GetBuffer returns the buffer, if any, inside this probe info.
func (p *PadProbeInfo) GetBuffer() *Buffer {
buf := C.gst_pad_probe_info_get_buffer(p.ptr)
if buf == nil {
return nil
}
return wrapBuffer(buf)
}
// GetBufferList returns the buffer list, if any, inside this probe info.
func (p *PadProbeInfo) GetBufferList() *BufferList {
bufList := C.gst_pad_probe_info_get_buffer_list(p.ptr)
if bufList == nil {
return nil
}
return wrapBufferList(bufList)
}
// GetEvent returns the event, if any, inside this probe info.
func (p *PadProbeInfo) GetEvent() *Event {
ev := C.gst_pad_probe_info_get_event(p.ptr)
if ev == nil {
return nil
}
return wrapEvent(ev)
}
// GetQuery returns the query, if any, inside this probe info.
func (p *PadProbeInfo) GetQuery() *Query {
q := C.gst_pad_probe_info_get_query(p.ptr)
if q == nil {
return nil
}
return wrapQuery(q)
}