diff --git a/examples/appsink/main.go b/examples/appsink/main.go index c8ceba5..54e7146 100644 --- a/examples/appsink/main.go +++ b/examples/appsink/main.go @@ -68,8 +68,8 @@ func createPipeline() (*gst.Pipeline, error) { // mode of access (read, read/write). // // We also know what format to expect because we set it with the caps. So we convert - // the map directly to signed 16-bit integers. - samples := buffer.Map(gst.MapRead).AsInt16Slice() + // the map directly to signed 16-bit little-endian integers. + samples := buffer.Map(gst.MapRead).AsInt16LESlice() defer buffer.Unmap() // Calculate the root mean square for the buffer diff --git a/examples/pad-probes/main.go b/examples/pad-probes/main.go index 6196c29..328c055 100644 --- a/examples/pad-probes/main.go +++ b/examples/pad-probes/main.go @@ -65,7 +65,7 @@ func padProbes(mainLoop *gst.MainLoop) error { // We know what format the data in the memory region has, since we requested // it by setting the fakesink's caps. So what we do here is interpret the // memory region we mapped as an array of signed 16 bit integers. - samples := mapInfo.AsInt16Slice() + samples := mapInfo.AsInt16LESlice() if len(samples) == 0 { return gst.PadProbeOK } diff --git a/examples/plugins/filesrc/filesrc.go b/examples/plugins/filesrc/filesrc.go index ce7c226..655600b 100644 --- a/examples/plugins/filesrc/filesrc.go +++ b/examples/plugins/filesrc/filesrc.go @@ -13,6 +13,7 @@ // $ go build -o libgstgofilesrc.so -buildmode c-shared . // // +//go:generate go run github.com/tinyzimmer/go-gst/gen/plugin-gen.go package main import ( diff --git a/gst/base/gst.go.h b/gst/base/gst.go.h index f3971a6..c88f994 100644 --- a/gst/base/gst.go.h +++ b/gst/base/gst.go.h @@ -1,13 +1,14 @@ #ifndef __GST_BASE_GO_H__ #define __GST_BASE_GO_H__ -#include -#include +#include inline GstBaseSink * toGstBaseSink (void *p) { return GST_BASE_SINK_CAST(p); } inline GstBaseSrc * toGstBaseSrc (void *p) { return GST_BASE_SRC_CAST(p); } +inline GstPushSrc * toGstPushSrc (void *p) { return GST_PUSH_SRC(p); } inline GstBaseSinkClass * toGstBaseSinkClass (void *p) { return (GstBaseSinkClass *)p; } inline GstBaseSrcClass * toGstBaseSrcClass (void *p) { return (GstBaseSrcClass *)p; } +inline GstPushSrcClass * toGstPushSrcClass (void *p) { return (GstPushSrcClass *)p; } #endif \ No newline at end of file diff --git a/gst/base/gst_flow_combiner.go b/gst/base/gst_flow_combiner.go new file mode 100644 index 0000000..70bf945 --- /dev/null +++ b/gst/base/gst_flow_combiner.go @@ -0,0 +1,78 @@ +package base + +/* +#include "gst.go.h" +*/ +import "C" +import ( + "unsafe" + + "github.com/tinyzimmer/go-gst/gst" +) + +// FlowCombiner is a helper structure for aggregating flow returns. This struct +// is not thread safe. +// For more information see https://gstreamer.freedesktop.org/documentation/base/gstflowcombiner.html?gi-language=c#GstFlowCombiner +type FlowCombiner struct{ ptr *C.GstFlowCombiner } + +func wrapFlowCombiner(ptr *C.GstFlowCombiner) *FlowCombiner { + return &FlowCombiner{ptr} +} + +// NewFlowCombiner creates a new flow combiner. Use Free() to free it. +func NewFlowCombiner() *FlowCombiner { + return wrapFlowCombiner(C.gst_flow_combiner_new()) +} + +// Instance returns the underlying GstFlowCombiner instance. +func (f *FlowCombiner) Instance() *C.GstFlowCombiner { return f.ptr } + +// AddPad adds a new pad to the FlowCombiner. A reference is taken on the pad. +func (f *FlowCombiner) AddPad(pad *gst.Pad) { + C.gst_flow_combiner_add_pad(f.Instance(), (*C.GstPad)(unsafe.Pointer(pad.Instance()))) +} + +// Clear will remove all pads and reset the combiner to its initial state. +func (f *FlowCombiner) Clear() { C.gst_flow_combiner_clear(f.Instance()) } + +// Free will free a FlowCombiner and all its internal data. +func (f *FlowCombiner) Free() { C.gst_flow_combiner_free(f.Instance()) } + +// Ref will increment the reference count on the FlowCombiner. +func (f *FlowCombiner) Ref() *FlowCombiner { + return wrapFlowCombiner(C.gst_flow_combiner_ref(f.Instance())) +} + +// RemovePad will remove a pad from the FlowCombiner. +func (f *FlowCombiner) RemovePad(pad *gst.Pad) { + C.gst_flow_combiner_remove_pad(f.Instance(), (*C.GstPad)(unsafe.Pointer(pad.Instance()))) +} + +// Reset flow combiner and all pads to their initial state without removing pads. +func (f *FlowCombiner) Reset() { C.gst_flow_combiner_reset(f.Instance()) } + +// Unref decrements the reference count on the Flow Combiner. +func (f *FlowCombiner) Unref() { C.gst_flow_combiner_unref(f.Instance()) } + +// UpdateFlow computes the combined flow return for the pads in it. +// +// The GstFlowReturn parameter should be the last flow return update for a pad in this GstFlowCombiner. +// It will use this value to be able to shortcut some combinations and avoid looking over all pads again. +// e.g. The last combined return is the same as the latest obtained GstFlowReturn. +func (f *FlowCombiner) UpdateFlow(fret gst.FlowReturn) gst.FlowReturn { + return gst.FlowReturn(C.gst_flow_combiner_update_flow(f.Instance(), C.GstFlowReturn(fret))) +} + +// UpdatePadFlow sets the provided pad's last flow return to provided value and computes the combined flow +// return for the pads in it. +// +// The GstFlowReturn parameter should be the last flow return update for a pad in this GstFlowCombiner. It +// will use this value to be able to shortcut some combinations and avoid looking over all pads again. e.g. +// The last combined return is the same as the latest obtained GstFlowReturn. +func (f *FlowCombiner) UpdatePadFlow(pad *gst.Pad, fret gst.FlowReturn) gst.FlowReturn { + return gst.FlowReturn(C.gst_flow_combiner_update_pad_flow( + f.Instance(), + (*C.GstPad)(unsafe.Pointer(pad.Instance())), + C.GstFlowReturn(fret), + )) +} diff --git a/gst/base/gst_push_src.go b/gst/base/gst_push_src.go new file mode 100644 index 0000000..9742522 --- /dev/null +++ b/gst/base/gst_push_src.go @@ -0,0 +1,30 @@ +package base + +/* +#include "gst.go.h" +*/ +import "C" + +import ( + "unsafe" + + "github.com/tinyzimmer/go-gst/gst" +) + +// GstPushSrc represents a GstBaseSrc. +type GstPushSrc struct{ *GstBaseSrc } + +// ToGstPushSrc returns a GstPushSrc object for the given object. +func ToGstPushSrc(obj *gst.Object) *GstPushSrc { + return &GstPushSrc{&GstBaseSrc{&gst.Element{Object: obj}}} +} + +// wrapGstPushSrc wraps the given unsafe.Pointer in a GstPushSrc instance. +func wrapGstPushSrc(obj *C.GstPushSrc) *GstPushSrc { + return &GstPushSrc{&GstBaseSrc{gst.FromGstElementUnsafe(unsafe.Pointer(obj))}} +} + +// Instance returns the underlying C GstBaseSrc instance +func (g *GstPushSrc) Instance() *C.GstPushSrc { + return C.toGstPushSrc(g.Unsafe()) +} diff --git a/gst/base/gst_push_src_exports.go b/gst/base/gst_push_src_exports.go new file mode 100644 index 0000000..ce07afb --- /dev/null +++ b/gst/base/gst_push_src_exports.go @@ -0,0 +1,46 @@ +package base + +/* +#include "gst.go.h" +*/ +import "C" + +import ( + "unsafe" + + "github.com/tinyzimmer/go-gst/gst" +) + +//export goGstPushSrcAlloc +func goGstPushSrcAlloc(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn { + caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface { + Alloc(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + }) + ret, buffer := caller.Alloc(wrapGstPushSrc(src)) + if ret != gst.FlowOK { + return C.GstFlowReturn(ret) + } + C.memcpy(unsafe.Pointer(*buf), unsafe.Pointer(buffer.Instance()), C.sizeof_GstBuffer) + return C.GstFlowReturn(ret) +} + +//export goGstPushSrcCreate +func goGstPushSrcCreate(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn { + caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface { + Create(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + }) + ret, buffer := caller.Create(wrapGstPushSrc(src)) + if ret != gst.FlowOK { + return C.GstFlowReturn(ret) + } + C.memcpy(unsafe.Pointer(*buf), unsafe.Pointer(buffer.Instance()), C.sizeof_GstBuffer) + return C.GstFlowReturn(ret) +} + +//export goGstPushSrcFill +func goGstPushSrcFill(src *C.GstPushSrc, buf *C.GstBuffer) C.GstFlowReturn { + caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface { + Fill(*GstPushSrc, *gst.Buffer) gst.FlowReturn + }) + return C.GstFlowReturn(caller.Fill(wrapGstPushSrc(src), gst.FromGstBufferUnsafe(unsafe.Pointer(buf)))) +} diff --git a/gst/base/gst_push_src_impl.go b/gst/base/gst_push_src_impl.go new file mode 100644 index 0000000..d5b6f18 --- /dev/null +++ b/gst/base/gst_push_src_impl.go @@ -0,0 +1,72 @@ +package base + +/* +#include "gst.go.h" + +extern GstFlowReturn goGstPushSrcAlloc (GstPushSrc * src, GstBuffer ** buf); +extern GstFlowReturn goGstPushSrcCreate (GstPushSrc * src, GstBuffer ** buf); +extern GstFlowReturn goGstPushSrcFill (GstPushSrc * src, GstBuffer * buf); + +void setGstPushSrcAlloc (GstPushSrcClass * klass) { klass->alloc = goGstPushSrcAlloc; } +void setGstPushSrcCreate (GstPushSrcClass * klass) { klass->create = goGstPushSrcCreate; } +void setGstPushSrcFill (GstPushSrcClass * klass) { klass->fill = goGstPushSrcFill; } + +*/ +import "C" +import ( + "unsafe" + + "github.com/tinyzimmer/go-glib/glib" + "github.com/tinyzimmer/go-gst/gst" +) + +var ( + // ExtendsPushSrc is an Extendable for extending a GstPushSrc + ExtendsPushSrc gst.Extendable = &extendsPushSrc{parent: ExtendsBaseSrc} +) + +// GstPushSrcImpl is the documented interface for an element extending a GstPushSrc. It does not have to +// be implemented in it's entirety. Each of the methods it declares will be checked for their presence +// in the initializing object, and if the object declares an override it will replace the default +// implementation in the virtual methods. +type GstPushSrcImpl interface { + // Asks the subclass to allocate a buffer. The subclass decides which size this buffer should be. + // The default implementation will create a new buffer from the negotiated allocator. + Alloc(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + // Asks the subclass to create a buffer. The subclass decides which size this buffer should be. Other + // then that, refer to GstBaseSrc.create for more details. If this method is not implemented, alloc + // followed by fill will be called. + Create(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + // Asks the subclass to fill the buffer with data. + Fill(*GstPushSrc, *gst.Buffer) gst.FlowReturn +} + +type extendsPushSrc struct{ parent gst.Extendable } + +func (e *extendsPushSrc) Type() glib.Type { return glib.Type(C.gst_push_src_get_type()) } +func (e *extendsPushSrc) ClassSize() int64 { return int64(C.sizeof_GstPushSrcClass) } +func (e *extendsPushSrc) InstanceSize() int64 { return int64(C.sizeof_GstPushSrc) } + +func (e *extendsPushSrc) InitClass(klass unsafe.Pointer, elem gst.GoElement) { + e.parent.InitClass(klass, elem) + + srcClass := C.toGstPushSrcClass(klass) + + if _, ok := elem.(interface { + Alloc(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + }); ok { + C.setGstPushSrcAlloc(srcClass) + } + + if _, ok := elem.(interface { + Create(*GstPushSrc) (gst.FlowReturn, *gst.Buffer) + }); ok { + C.setGstPushSrcCreate(srcClass) + } + + if _, ok := elem.(interface { + Fill(*GstPushSrc, *gst.Buffer) gst.FlowReturn + }); ok { + C.setGstPushSrcFill(srcClass) + } +} diff --git a/gst/base/gst_type_find.go b/gst/base/gst_type_find.go new file mode 100644 index 0000000..dc2951a --- /dev/null +++ b/gst/base/gst_type_find.go @@ -0,0 +1,152 @@ +package base + +/* +#include "gst.go.h" +*/ +import "C" + +import ( + "unsafe" + + "github.com/tinyzimmer/go-gst/gst" +) + +// TypeFindHelper tries to find what type of data is flowing from the given source GstPad. +// Returns nil if no Caps matches the data stream. Unref after usage. +func TypeFindHelper(pad *gst.Pad, size uint64) *gst.Caps { + caps := C.gst_type_find_helper((*C.GstPad)(unsafe.Pointer(pad.Instance())), C.guint64(size)) + if caps == nil { + return nil + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)) +} + +// TypeFindHelperForBuffer tries to find what type of data is contained in the given GstBuffer, +// the assumption being that the buffer represents the beginning of the stream or file. +// +// All available typefinders will be called on the data in order of rank. If a typefinding function +// returns a probability of gst.TypeFindMaximum, typefinding is stopped immediately and the found +// caps will be returned right away. Otherwise, all available typefind functions will the tried, and +// the caps with the highest probability will be returned, or nil if the content of the buffer could +// not be identified. +// +// Object can either be nil or the object doing the typefinding (used for logging). Caps should be unrefed +// after usage. +func TypeFindHelperForBuffer(obj *gst.Object, buffer *gst.Buffer) (*gst.Caps, gst.TypeFindProbability) { + var prob C.GstTypeFindProbability + var cobj *C.GstObject + if obj != nil { + cobj = (*C.GstObject)(obj.Unsafe()) + } + caps := C.gst_type_find_helper_for_buffer(cobj, (*C.GstBuffer)(unsafe.Pointer(buffer.Instance())), &prob) + if caps == nil { + return nil, gst.TypeFindProbability(prob) + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)), gst.TypeFindProbability(prob) +} + +// TypeFindHelperForBufferWithExtension ries to find what type of data is contained in the given GstBuffer, +// the assumption being that the buffer represents the beginning of the stream or file. +// +// All available typefinders will be called on the data in order of rank. If a typefinding function returns +// a probability of gst.TypeFindMaximum, typefinding is stopped immediately and the found caps will be returned +// right away. Otherwise, all available typefind functions will the tried, and the caps with the highest +// probability will be returned, or nil if the content of the buffer could not be identified. +// +// When extension is not empty, this function will first try the typefind functions for the given extension, +// which might speed up the typefinding in many cases. +// +// Unref caps after usage. +func TypeFindHelperForBufferWithExtension(obj *gst.Object, buffer *gst.Buffer, extension string) (*gst.Caps, gst.TypeFindProbability) { + var prob C.GstTypeFindProbability + var cobj *C.GstObject + var cext *C.gchar + if obj != nil { + cobj = (*C.GstObject)(obj.Unsafe()) + } + if extension != "" { + cstr := C.CString(extension) + defer C.free(unsafe.Pointer(cstr)) + cext = (*C.gchar)(unsafe.Pointer(cstr)) + } + caps := C.gst_type_find_helper_for_buffer_with_extension(cobj, (*C.GstBuffer)(unsafe.Pointer(buffer.Instance())), cext, &prob) + if caps == nil { + return nil, gst.TypeFindProbability(prob) + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)), gst.TypeFindProbability(prob) +} + +// TypeFindHelperForData tries to find what type of data is contained in the given data, +// the assumption being that the buffer represents the beginning of the stream or file. +// +// All available typefinders will be called on the data in order of rank. If a typefinding function +// returns a probability of gst.TypeFindMaximum, typefinding is stopped immediately and the found +// caps will be returned right away. Otherwise, all available typefind functions will the tried, and +// the caps with the highest probability will be returned, or nil if the content of the buffer could +// not be identified. +// +// Object can either be nil or the object doing the typefinding (used for logging). Caps should be unrefed +// after usage. +func TypeFindHelperForData(obj *gst.Object, data []byte) (*gst.Caps, gst.TypeFindProbability) { + var prob C.GstTypeFindProbability + var cobj *C.GstObject + if obj != nil { + cobj = (*C.GstObject)(obj.Unsafe()) + } + caps := C.gst_type_find_helper_for_data(cobj, (*C.guint8)(unsafe.Pointer(&data[0])), C.gsize(len(data)), &prob) + if caps == nil { + return nil, gst.TypeFindProbability(prob) + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)), gst.TypeFindProbability(prob) +} + +// TypeFindHelperForDataWithExtension ries to find what type of data is contained in the given data, +// the assumption being that the buffer represents the beginning of the stream or file. +// +// All available typefinders will be called on the data in order of rank. If a typefinding function returns +// a probability of gst.TypeFindMaximum, typefinding is stopped immediately and the found caps will be returned +// right away. Otherwise, all available typefind functions will the tried, and the caps with the highest +// probability will be returned, or nil if the content of the buffer could not be identified. +// +// When extension is not empty, this function will first try the typefind functions for the given extension, +// which might speed up the typefinding in many cases. +// +// Object can either be nil or the object doing the typefinding (used for logging). Unref caps after usage. +func TypeFindHelperForDataWithExtension(obj *gst.Object, data []byte, extension string) (*gst.Caps, gst.TypeFindProbability) { + var prob C.GstTypeFindProbability + var cobj *C.GstObject + var cext *C.gchar + if obj != nil { + cobj = (*C.GstObject)(obj.Unsafe()) + } + if extension != "" { + cstr := C.CString(extension) + defer C.free(unsafe.Pointer(cstr)) + cext = (*C.gchar)(unsafe.Pointer(cstr)) + } + caps := C.gst_type_find_helper_for_data_with_extension(cobj, (*C.guint8)(unsafe.Pointer(&data[0])), C.gsize(len(data)), cext, &prob) + if caps == nil { + return nil, gst.TypeFindProbability(prob) + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)), gst.TypeFindProbability(prob) +} + +// TypeFindHelperForExtension tries to find the best GstCaps associated with extension. +// +// All available typefinders will be checked against the extension in order of rank. The caps of the first typefinder +// that can handle extension will be returned. +// +// Object can either be nil or the object doing the typefinding (used for logging). Unref caps after usage. +func TypeFindHelperForExtension(obj *gst.Object, extension string) *gst.Caps { + var cobj *C.GstObject + if obj != nil { + cobj = (*C.GstObject)(obj.Unsafe()) + } + cext := C.CString(extension) + defer C.free(unsafe.Pointer(cext)) + caps := C.gst_type_find_helper_for_extension(cobj, (*C.gchar)(unsafe.Pointer(cext))) + if caps == nil { + return nil + } + return gst.FromGstCapsUnsafe(unsafe.Pointer(caps)) +} diff --git a/gst/constants.go b/gst/constants.go index 878f8aa..bd6fbc2 100644 --- a/gst/constants.go +++ b/gst/constants.go @@ -1046,3 +1046,17 @@ const ( TagVersion Tag = C.GST_TAG_VERSION TagVideoCodec Tag = C.GST_TAG_VIDEO_CODEC ) + +// TypeFindProbability represents a probability for type find functions. Higher values +// reflect higher certainty. +type TypeFindProbability int + +// Type castings +const ( + TypeFindNone TypeFindProbability = C.GST_TYPE_FIND_NONE // (0) – type undetected. + TypeFindMinimum TypeFindProbability = C.GST_TYPE_FIND_MINIMUM // (1) – unlikely typefind. + TypeFindPossible TypeFindProbability = C.GST_TYPE_FIND_POSSIBLE // (50) – possible type detected. + TypeFindLikely TypeFindProbability = C.GST_TYPE_FIND_LIKELY // (80) – likely a type was detected. + TypeFindNearlyCertain TypeFindProbability = C.GST_TYPE_FIND_NEARLY_CERTAIN // (99) – nearly certain that a type was detected. + TypeFindMaximum TypeFindProbability = C.GST_TYPE_FIND_MAXIMUM // (100) – very certain a type was detected. +) diff --git a/gst/gst.go.h b/gst/gst.go.h index d2af847..4495ee0 100644 --- a/gst/gst.go.h +++ b/gst/gst.go.h @@ -3,7 +3,7 @@ #include #include -#include +#include /* Type Castings diff --git a/gst/gst_mapinfo.go b/gst/gst_mapinfo.go index d9eaf45..494192d 100644 --- a/gst/gst_mapinfo.go +++ b/gst/gst_mapinfo.go @@ -5,12 +5,29 @@ package gst void memcpy_offset (void * dest, guint offset, const void * src, size_t n) { memcpy(dest + offset, src, n); } + +GstByteReader * newByteReader (const guint8 * data, guint size) +{ + GstByteReader *ret = g_slice_new0 (GstByteReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +void freeByteReader (GstByteReader * reader) +{ + g_return_if_fail (reader != NULL); + g_slice_free (GstByteReader, reader); +} + + */ import "C" import ( "bytes" - "encoding/binary" "errors" "io" "unsafe" @@ -97,79 +114,234 @@ func (m *MapInfo) Bytes() []byte { // AsInt8Slice returns the contents of this map as a slice of signed 8-bit integers. func (m *MapInfo) AsInt8Slice() []int8 { - uint8sl := m.AsUint8Slice() - out := make([]int8, m.Size()) - for i := range out { - out[i] = int8(uint8sl[i]) + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int8, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint8 + C.gst_byte_reader_get_int8(br, &gint) + out = append(out, int8(gint)) } return out } -// AsInt16Slice returns the contents of this map as a slice of signed 16-bit integers. -func (m *MapInfo) AsInt16Slice() []int16 { - uint8sl := m.AsUint8Slice() - out := make([]int16, m.Size()/2) - for i := range out { - out[i] = int16(binary.LittleEndian.Uint16(uint8sl[i*2 : (i+1)*2])) +// AsInt16BESlice returns the contents of this map as a slice of signed 16-bit big-endian integers. +func (m *MapInfo) AsInt16BESlice() []int16 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int16, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint16 + C.gst_byte_reader_get_int16_be(br, &gint) + out = append(out, int16(gint)) } return out } -// AsInt32Slice returns the contents of this map as a slice of signed 32-bit integers. -func (m *MapInfo) AsInt32Slice() []int32 { - uint8sl := m.AsUint8Slice() - out := make([]int32, m.Size()/4) - for i := range out { - out[i] = int32(binary.LittleEndian.Uint32(uint8sl[i*4 : (i+1)*4])) +// AsInt16LESlice returns the contents of this map as a slice of signed 16-bit little-endian integers. +func (m *MapInfo) AsInt16LESlice() []int16 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int16, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint16 + C.gst_byte_reader_get_int16_le(br, &gint) + out = append(out, int16(gint)) } return out } -// AsInt64Slice returns the contents of this map as a slice of signed 64-bit integers. -func (m *MapInfo) AsInt64Slice() []int64 { - uint8sl := m.AsUint8Slice() - out := make([]int64, m.Size()/8) - for i := range out { - out[i] = int64(binary.LittleEndian.Uint64(uint8sl[i*8 : (i+1)*8])) +// AsInt32BESlice returns the contents of this map as a slice of signed 32-bit big-endian integers. +func (m *MapInfo) AsInt32BESlice() []int32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint32 + C.gst_byte_reader_get_int32_be(br, &gint) + out = append(out, int32(gint)) + } + return out +} + +// AsInt32LESlice returns the contents of this map as a slice of signed 32-bit little-endian integers. +func (m *MapInfo) AsInt32LESlice() []int32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint32 + C.gst_byte_reader_get_int32_le(br, &gint) + out = append(out, int32(gint)) + } + return out +} + +// AsInt64BESlice returns the contents of this map as a slice of signed 64-bit big-endian integers. +func (m *MapInfo) AsInt64BESlice() []int64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint64 + C.gst_byte_reader_get_int64_be(br, &gint) + out = append(out, int64(gint)) + } + return out +} + +// AsInt64LESlice returns the contents of this map as a slice of signed 64-bit little-endian integers. +func (m *MapInfo) AsInt64LESlice() []int64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]int64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gint64 + C.gst_byte_reader_get_int64_le(br, &gint) + out = append(out, int64(gint)) } return out } // AsUint8Slice returns the contents of this map as a slice of unsigned 8-bit integers. func (m *MapInfo) AsUint8Slice() []uint8 { - out := make([]uint8, m.Size()) - for i, t := range (*[1 << 30]uint8)(m.Data())[:m.Size():m.Size()] { - out[i] = t + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint8, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint8 + C.gst_byte_reader_get_uint8(br, &gint) + out = append(out, uint8(gint)) } return out } -// AsUint16Slice returns the contents of this map as a slice of unsigned 16-bit integers. -func (m *MapInfo) AsUint16Slice() []uint16 { - uint8sl := m.AsUint8Slice() - out := make([]uint16, m.Size()/2) - for i := range out { - out[i] = uint16(binary.LittleEndian.Uint16(uint8sl[i*2 : (i+1)*2])) +// AsUint16BESlice returns the contents of this map as a slice of unsigned 16-bit big-endian integers. +func (m *MapInfo) AsUint16BESlice() []uint16 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint16, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint16 + C.gst_byte_reader_get_uint16_be(br, &gint) + out = append(out, uint16(gint)) } return out } -// AsUint32Slice returns the contents of this map as a slice of unsigned 32-bit integers. -func (m *MapInfo) AsUint32Slice() []uint32 { - uint8sl := m.AsUint8Slice() - out := make([]uint32, m.Size()/4) - for i := range out { - out[i] = uint32(binary.LittleEndian.Uint32(uint8sl[i*4 : (i+1)*4])) +// AsUint16LESlice returns the contents of this map as a slice of unsigned 16-bit little-endian integers. +func (m *MapInfo) AsUint16LESlice() []uint16 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint16, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint16 + C.gst_byte_reader_get_uint16_le(br, &gint) + out = append(out, uint16(gint)) } return out } -// AsUint64Slice returns the contents of this map as a slice of unsigned 64-bit integers. -func (m *MapInfo) AsUint64Slice() []uint64 { - uint8sl := m.AsUint8Slice() - out := make([]uint64, m.Size()/8) - for i := range out { - out[i] = uint64(binary.LittleEndian.Uint64(uint8sl[i*8 : (i+1)*8])) +// AsUint32BESlice returns the contents of this map as a slice of unsigned 32-bit big-endian integers. +func (m *MapInfo) AsUint32BESlice() []uint32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint32 + C.gst_byte_reader_get_uint32_be(br, &gint) + out = append(out, uint32(gint)) + } + return out +} + +// AsUint32LESlice returns the contents of this map as a slice of unsigned 32-bit little-endian integers. +func (m *MapInfo) AsUint32LESlice() []uint32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint32 + C.gst_byte_reader_get_uint32_le(br, &gint) + out = append(out, uint32(gint)) + } + return out +} + +// AsUint64BESlice returns the contents of this map as a slice of unsigned 64-bit big-endian integers. +func (m *MapInfo) AsUint64BESlice() []uint64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint64 + C.gst_byte_reader_get_uint64_be(br, &gint) + out = append(out, uint64(gint)) + } + return out +} + +// AsUint64LESlice returns the contents of this map as a slice of unsigned 64-bit little-endian integers. +func (m *MapInfo) AsUint64LESlice() []uint64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]uint64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.guint64 + C.gst_byte_reader_get_uint64_le(br, &gint) + out = append(out, uint64(gint)) + } + return out +} + +// AsFloat32BESlice returns the contents of this map as a slice of 32-bit big-endian floats. +func (m *MapInfo) AsFloat32BESlice() []float32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]float32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gfloat + C.gst_byte_reader_get_float32_be(br, &gint) + out = append(out, float32(gint)) + } + return out +} + +// AsFloat32LESlice returns the contents of this map as a slice of 32-bit little-endian floats. +func (m *MapInfo) AsFloat32LESlice() []float32 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]float32, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gfloat + C.gst_byte_reader_get_float32_le(br, &gint) + out = append(out, float32(gint)) + } + return out +} + +// AsFloat64BESlice returns the contents of this map as a slice of 64-bit big-endian floats. +func (m *MapInfo) AsFloat64BESlice() []float64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]float64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gdouble + C.gst_byte_reader_get_float64_be(br, &gint) + out = append(out, float64(gint)) + } + return out +} + +// AsFloat64LESlice returns the contents of this map as a slice of 64-bit little-endian floats. +func (m *MapInfo) AsFloat64LESlice() []float64 { + br := C.newByteReader(m.Instance().data, C.guint(m.Instance().size)) + defer C.freeByteReader(br) + out := make([]float64, 0) + for C.gst_byte_reader_get_remaining(br) != C.guint(0) { + var gint C.gdouble + C.gst_byte_reader_get_float64_le(br, &gint) + out = append(out, float64(gint)) } return out }