mirror of
https://github.com/go-gst/go-gst.git
synced 2025-11-02 20:34:01 +08:00
finish allocator and meta implementations, add meta implementation to buffers
This commit is contained in:
@@ -31,6 +31,16 @@ func goStrings(argc C.int, argv **C.gchar) []string {
|
|||||||
return gostrings
|
return gostrings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gcharStrings(strs []string) **C.gchar {
|
||||||
|
gcharSlc := make([]*C.gchar, len(strs))
|
||||||
|
for _, s := range strs {
|
||||||
|
cStr := C.CString(s)
|
||||||
|
defer C.free(unsafe.Pointer(cStr))
|
||||||
|
gcharSlc = append(gcharSlc, cStr)
|
||||||
|
}
|
||||||
|
return &gcharSlc[0]
|
||||||
|
}
|
||||||
|
|
||||||
// newQuarkFromString creates a new GQuark (or returns an existing one) for the given
|
// newQuarkFromString creates a new GQuark (or returns an existing one) for the given
|
||||||
// string
|
// string
|
||||||
func newQuarkFromString(str string) C.uint {
|
func newQuarkFromString(str string) C.uint {
|
||||||
@@ -39,3 +49,7 @@ func newQuarkFromString(str string) C.uint {
|
|||||||
quark := C.g_quark_from_string(cstr)
|
quark := C.g_quark_from_string(cstr)
|
||||||
return quark
|
return quark
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func quarkToString(q C.GQuark) string {
|
||||||
|
return C.GoString(C.g_quark_to_string(q))
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,3 +56,55 @@ func goBusFunc(bus *C.GstBus, cMsg *C.GstMessage, userData C.gpointer) C.gboolea
|
|||||||
|
|
||||||
return gboolean(true)
|
return gboolean(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMetaInfoCbFuncs(meta *C.GstMeta) *MetaInfoCallbackFuncs {
|
||||||
|
return registeredMetas[glib.Type(meta.info._type)]
|
||||||
|
}
|
||||||
|
|
||||||
|
//export goMetaFreeFunc
|
||||||
|
func goMetaFreeFunc(meta *C.GstMeta, buf *C.GstBuffer) {
|
||||||
|
cbFuncs := getMetaInfoCbFuncs(meta)
|
||||||
|
if cbFuncs != nil && cbFuncs.FreeFunc != nil {
|
||||||
|
cbFuncs.FreeFunc(wrapBuffer(buf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export goMetaInitFunc
|
||||||
|
func goMetaInitFunc(meta *C.GstMeta, params C.gpointer, buf *C.GstBuffer) C.gboolean {
|
||||||
|
cbFuncs := getMetaInfoCbFuncs(meta)
|
||||||
|
if cbFuncs != nil && cbFuncs.InitFunc != nil {
|
||||||
|
paramsIface := gopointer.Restore(unsafe.Pointer(params))
|
||||||
|
defer gopointer.Unref(unsafe.Pointer(params))
|
||||||
|
return gboolean(cbFuncs.InitFunc(paramsIface, wrapBuffer(buf)))
|
||||||
|
}
|
||||||
|
return gboolean(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export goMetaTransformFunc
|
||||||
|
func goMetaTransformFunc(transBuf *C.GstBuffer, meta *C.GstMeta, buffer *C.GstBuffer, mType C.GQuark, data C.gpointer) C.gboolean {
|
||||||
|
cbFuncs := getMetaInfoCbFuncs(meta)
|
||||||
|
if cbFuncs != nil && cbFuncs.TransformFunc != nil {
|
||||||
|
transformData := (*C.GstMetaTransformCopy)(unsafe.Pointer(data))
|
||||||
|
return gboolean(cbFuncs.TransformFunc(
|
||||||
|
wrapBuffer(transBuf),
|
||||||
|
wrapBuffer(buffer),
|
||||||
|
quarkToString(mType),
|
||||||
|
&MetaTransformCopy{
|
||||||
|
Region: gobool(transformData.region),
|
||||||
|
Offset: int64(transformData.offset),
|
||||||
|
Size: int64(transformData.size),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return gboolean(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export goGDestroyNotifyFunc
|
||||||
|
func goGDestroyNotifyFunc(ptr C.gpointer) {
|
||||||
|
funcIface := gopointer.Restore(unsafe.Pointer(ptr))
|
||||||
|
defer gopointer.Unref(unsafe.Pointer(ptr))
|
||||||
|
f := funcIface.(func())
|
||||||
|
if f != nil {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ func NewAllocationParams() *AllocationParams {
|
|||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instance returns the underlying GstAllocationParams.
|
||||||
|
func (a *AllocationParams) Instance() *C.GstAllocationParams { return a.ptr }
|
||||||
|
|
||||||
// Init initializes these AllocationParams to their original values.
|
// Init initializes these AllocationParams to their original values.
|
||||||
func (a *AllocationParams) Init() { C.gst_allocation_params_init(a.ptr) }
|
func (a *AllocationParams) Init() { C.gst_allocation_params_init(a.ptr) }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
package gst
|
package gst
|
||||||
|
|
||||||
// #include "gst.go.h"
|
/*
|
||||||
|
#include "gst.go.h"
|
||||||
|
|
||||||
|
extern void goGDestroyNotifyFunc (gpointer data);
|
||||||
|
|
||||||
|
void cgoDestroyNotifyFunc (gpointer data) {
|
||||||
|
goGDestroyNotifyFunc(data);
|
||||||
|
}
|
||||||
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -11,6 +19,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/glib"
|
"github.com/gotk3/gotk3/glib"
|
||||||
|
gopointer "github.com/mattn/go-pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Buffer is a go representation of a GstBuffer.
|
// Buffer is a go representation of a GstBuffer.
|
||||||
@@ -18,6 +27,30 @@ type Buffer struct {
|
|||||||
ptr *C.GstBuffer
|
ptr *C.GstBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEmptyBuffer returns a new empty buffer.
|
||||||
|
func NewEmptyBuffer() *Buffer {
|
||||||
|
return wrapBuffer(C.gst_buffer_new())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBufferAllocate tries to create a newly allocated buffer with data of the given size
|
||||||
|
// and extra parameters from allocator. If the requested amount of memory can't be allocated,
|
||||||
|
// nil will be returned. The allocated buffer memory is not cleared.
|
||||||
|
//
|
||||||
|
// When allocator is nil, the default memory allocator will be used.
|
||||||
|
//
|
||||||
|
// Note that when size == 0, the buffer will not have memory associated with it.
|
||||||
|
func NewBufferAllocate(alloc *Allocator, params *AllocationParams, size int64) *Buffer {
|
||||||
|
var gstalloc *C.GstAllocator
|
||||||
|
if alloc != nil {
|
||||||
|
gstalloc = alloc.Instance()
|
||||||
|
}
|
||||||
|
buf := C.gst_buffer_new_allocate(gstalloc, C.gsize(size), params.Instance())
|
||||||
|
if buf == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return wrapBuffer(buf)
|
||||||
|
}
|
||||||
|
|
||||||
// NewBufferFromBytes returns a new buffer from the given byte slice.
|
// NewBufferFromBytes returns a new buffer from the given byte slice.
|
||||||
func NewBufferFromBytes(b []byte) *Buffer {
|
func NewBufferFromBytes(b []byte) *Buffer {
|
||||||
str := string(b)
|
str := string(b)
|
||||||
@@ -36,9 +69,54 @@ func NewBufferFromReader(rdr io.Reader) (*Buffer, error) {
|
|||||||
return NewBufferFromBytes(out), nil
|
return NewBufferFromBytes(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBufferFull allocates a new buffer that wraps the given data. The wrapped buffer will
|
||||||
|
// have the region from offset and size visible. The maxsize must be at least the size of the
|
||||||
|
// data provided.
|
||||||
|
//
|
||||||
|
// When the buffer is destroyed, notifyFunc will be called if it is not nil.
|
||||||
|
//
|
||||||
|
// The prefix/padding must be filled with 0 if flags contains MemoryFlagZeroPrefixed and MemoryFlagZeroPadded respectively.
|
||||||
|
//
|
||||||
|
// Example
|
||||||
|
//
|
||||||
|
// buf := gst.NewBufferFull(0, []byte("hello-world"), 1024, 0, 1024, func() {
|
||||||
|
// fmt.Println("buffer was destroyed")
|
||||||
|
// })
|
||||||
|
// if buf != nil {
|
||||||
|
// buf.Unref()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // > buffer was destroyed
|
||||||
|
func NewBufferFull(flags MemoryFlags, data []byte, maxSize, offset, size int64, notifyFunc func()) *Buffer {
|
||||||
|
var notifyData unsafe.Pointer
|
||||||
|
var gnotifyFunc C.GDestroyNotify
|
||||||
|
if notifyFunc != nil {
|
||||||
|
notifyData = gopointer.Save(notifyFunc)
|
||||||
|
gnotifyFunc = C.GDestroyNotify(C.cgoDestroyNotifyFunc)
|
||||||
|
}
|
||||||
|
dataStr := string(data)
|
||||||
|
dataPtr := unsafe.Pointer(C.CString(dataStr))
|
||||||
|
buf := C.gst_buffer_new_wrapped_full(
|
||||||
|
C.GstMemoryFlags(flags),
|
||||||
|
(C.gpointer)(dataPtr),
|
||||||
|
C.gsize(maxSize), C.gsize(offset), C.gsize(size),
|
||||||
|
(C.gpointer)(notifyData), gnotifyFunc,
|
||||||
|
)
|
||||||
|
if buf == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return wrapBuffer(buf)
|
||||||
|
}
|
||||||
|
|
||||||
// Instance returns the underlying GstBuffer instance.
|
// Instance returns the underlying GstBuffer instance.
|
||||||
func (b *Buffer) Instance() *C.GstBuffer { return C.toGstBuffer(unsafe.Pointer(b.ptr)) }
|
func (b *Buffer) Instance() *C.GstBuffer { return C.toGstBuffer(unsafe.Pointer(b.ptr)) }
|
||||||
|
|
||||||
|
// Ref increases the ref count on the buffer by one.
|
||||||
|
func (b *Buffer) Ref() *Buffer { return wrapBuffer(C.gst_buffer_ref(b.Instance())) }
|
||||||
|
|
||||||
|
// Unref decreaes the ref count on the buffer by one. When the refcount reaches zero, the memory is freed.
|
||||||
|
func (b *Buffer) Unref() { C.gst_buffer_unref(b.Instance()) }
|
||||||
|
|
||||||
// Reader returns an io.Reader for this buffer.
|
// Reader returns an io.Reader for this buffer.
|
||||||
func (b *Buffer) Reader() io.Reader { return bytes.NewBuffer(b.Bytes()) }
|
func (b *Buffer) Reader() io.Reader { return bytes.NewBuffer(b.Bytes()) }
|
||||||
|
|
||||||
@@ -104,6 +182,39 @@ func (b *Buffer) Map() *MapInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMeta adds metadata for info to the buffer using the parameters in params. The given
|
||||||
|
// parameters are passed to the MetaInfo's init function, and as such will only work
|
||||||
|
// for MetaInfo objects created from the go runtime.
|
||||||
|
//
|
||||||
|
// Example
|
||||||
|
//
|
||||||
|
// metaInfo := gst.RegisterMeta(glib.TypeFromName("GstObject"), "my-meta", 1024, &gst.MetaInfoCallbackFuncs{
|
||||||
|
// InitFunc: func(params interface{}, buffer *gst.Buffer) bool {
|
||||||
|
// paramStr := params.(string)
|
||||||
|
// fmt.Println("Buffer initialized with params:", paramStr)
|
||||||
|
// return true
|
||||||
|
// },
|
||||||
|
// FreeFunc: func(buffer *gst.Buffer) {
|
||||||
|
// fmt.Println("Buffer was destroyed")
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// buf := gst.NewEmptyBuffer()
|
||||||
|
// buf.AddMeta(metaInfo, "hello world")
|
||||||
|
//
|
||||||
|
// buf.Unref()
|
||||||
|
//
|
||||||
|
// // > Buffer initialized with params: hello world
|
||||||
|
// // > Buffer was destroyed
|
||||||
|
//
|
||||||
|
func (b *Buffer) AddMeta(info *MetaInfo, params interface{}) *Meta {
|
||||||
|
meta := C.gst_buffer_add_meta(b.Instance(), info.Instance(), (C.gpointer)(gopointer.Save(params)))
|
||||||
|
if meta == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return wrapMeta(meta)
|
||||||
|
}
|
||||||
|
|
||||||
// GetMeta retrieves the metadata on the buffer for the given api. If none exists
|
// GetMeta retrieves the metadata on the buffer for the given api. If none exists
|
||||||
// then nil is returned.
|
// then nil is returned.
|
||||||
func (b *Buffer) GetMeta(api glib.Type) *Meta {
|
func (b *Buffer) GetMeta(api glib.Type) *Meta {
|
||||||
|
|||||||
106
gst/gst_meta.go
106
gst/gst_meta.go
@@ -1,6 +1,28 @@
|
|||||||
package gst
|
package gst
|
||||||
|
|
||||||
// #include "gst.go.h"
|
/*
|
||||||
|
#include "gst.go.h"
|
||||||
|
|
||||||
|
extern void goMetaFreeFunc (GstMeta * meta, GstBuffer * buffer);
|
||||||
|
extern gboolean goMetaInitFunc (GstMeta *meta, gpointer params, GstBuffer * buffer);
|
||||||
|
extern gboolean goMetaTransformFunc (GstBuffer * transBuf, GstMeta * meta, GstBuffer * buffer, GQuark type, gpointer data);
|
||||||
|
|
||||||
|
void cgoMetaFreeFunc (GstMeta * meta, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
goMetaFreeFunc(meta, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean cgoMetaInitFunc (GstMeta * meta, gpointer params, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
return goMetaInitFunc(meta, params, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean cgoMetaTransformFunc (GstBuffer * transBuf, GstMeta * meta, GstBuffer * buffer, GQuark type, gpointer data)
|
||||||
|
{
|
||||||
|
return goMetaTransformFunc(transBuf, meta, buffer, type, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -27,6 +49,88 @@ type MetaInfo struct {
|
|||||||
ptr *C.GstMetaInfo
|
ptr *C.GstMetaInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterAPIType registers and returns a GType for the given api name and associates it with tags.
|
||||||
|
func RegisterAPIType(name string, tags []string) glib.Type {
|
||||||
|
cTags := gcharStrings(tags)
|
||||||
|
defer C.g_free((C.gpointer)(unsafe.Pointer(cTags)))
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
newType := C.gst_meta_api_type_register((*C.gchar)(cName), cTags)
|
||||||
|
return glib.Type(newType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPIInfo gets the MetaInfo for the given api type.
|
||||||
|
func GetAPIInfo(name string) *MetaInfo {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
return wrapMetaInfo(C.gst_meta_get_info((*C.gchar)(cName)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPITags retrieves the tags for the given api type.
|
||||||
|
func GetAPITags(apiType glib.Type) []string {
|
||||||
|
tags := C.gst_meta_api_type_get_tags(C.GType(apiType))
|
||||||
|
return goStrings(C.sizeOfGCharArray(tags), tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIHasTag returns true if the given api has the given tag.
|
||||||
|
func APIHasTag(api glib.Type, tag string) bool {
|
||||||
|
q := newQuarkFromString(tag)
|
||||||
|
return gobool(C.gst_meta_api_type_has_tag(C.GType(api), q))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetaInitFunc is a function called when meta is initialized in buffer.
|
||||||
|
type MetaInitFunc func(params interface{}, buffer *Buffer) bool
|
||||||
|
|
||||||
|
// MetaFreeFunc is a function called when meta is freed in buffer.
|
||||||
|
type MetaFreeFunc func(buffer *Buffer)
|
||||||
|
|
||||||
|
// MetaTransformFunc is a function called for each meta in buf as a result
|
||||||
|
// of performing a transformation on transbuf. Additional type specific transform
|
||||||
|
// data is passed to the function as data.
|
||||||
|
type MetaTransformFunc func(transBuf, buf *Buffer, mType string, data *MetaTransformCopy) bool
|
||||||
|
|
||||||
|
// MetaTransformCopy is extra data passed to a MetaTransformFunc
|
||||||
|
type MetaTransformCopy struct {
|
||||||
|
// true if only region is copied
|
||||||
|
Region bool
|
||||||
|
// the offset to copy, 0 if region is FALSE, otherwise > 0
|
||||||
|
Offset int64
|
||||||
|
// the size to copy, -1 or the buffer size when region is FALSE
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetaInfoCallbackFuncs represents callback functions to includ when registering a new
|
||||||
|
// meta type.
|
||||||
|
type MetaInfoCallbackFuncs struct {
|
||||||
|
InitFunc MetaInitFunc
|
||||||
|
FreeFunc MetaFreeFunc
|
||||||
|
TransformFunc MetaTransformFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register metas internally as well so we can track callback functions
|
||||||
|
var registeredMetas = make(map[glib.Type]*MetaInfoCallbackFuncs)
|
||||||
|
|
||||||
|
// RegisterMeta registers and returns a new MetaInfo instance denoting the
|
||||||
|
// given type, name, and size.
|
||||||
|
func RegisterMeta(api glib.Type, name string, size int64, cbFuncs *MetaInfoCallbackFuncs) *MetaInfo {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
metaInfo := C.gst_meta_register(
|
||||||
|
C.GType(api),
|
||||||
|
(*C.gchar)(unsafe.Pointer(cName)),
|
||||||
|
C.gsize(size),
|
||||||
|
C.GstMetaInitFunction(C.cgoMetaInitFunc),
|
||||||
|
C.GstMetaFreeFunction(C.cgoMetaFreeFunc),
|
||||||
|
C.GstMetaTransformFunction(C.cgoMetaTransformFunc),
|
||||||
|
)
|
||||||
|
if metaInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
wrapped := wrapMetaInfo(metaInfo)
|
||||||
|
registeredMetas[wrapped.Type()] = cbFuncs
|
||||||
|
return wrapped
|
||||||
|
}
|
||||||
|
|
||||||
// Instance returns the underlying GstMetaInfo instance.
|
// Instance returns the underlying GstMetaInfo instance.
|
||||||
func (m *MetaInfo) Instance() *C.GstMetaInfo { return m.ptr }
|
func (m *MetaInfo) Instance() *C.GstMetaInfo { return m.ptr }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user