mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-05 07:56:51 +08:00
Buffer and Memory Optimizations (#6)
* Fixes for memory leaks when creating or mapping the contents of a buffer * Unmap methods on Buffer and Memory objects for required use after utilizing their Map methods * Optimize MapInfo.WriteData to use memcpy * Re-implement BufferFromBytes using GBytes and `gst_buffer_new_wrapped_bytes` instead of `gst_buffer_new_wrapped`.
This commit is contained in:
@@ -70,6 +70,7 @@ func createPipeline() (*gst.Pipeline, error) {
|
|||||||
// We also know what format to expect because we set it with the caps. So we convert
|
// 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.
|
// the map directly to signed 16-bit integers.
|
||||||
samples := buffer.Map(gst.MapRead).AsInt16Slice()
|
samples := buffer.Map(gst.MapRead).AsInt16Slice()
|
||||||
|
defer buffer.Unmap()
|
||||||
|
|
||||||
// Calculate the root mean square for the buffer
|
// Calculate the root mean square for the buffer
|
||||||
// (https://en.wikipedia.org/wiki/Root_mean_square)
|
// (https://en.wikipedia.org/wiki/Root_mean_square)
|
||||||
|
@@ -71,11 +71,11 @@ func createPipeline() (*gst.Pipeline, error) {
|
|||||||
fmt.Println("Producing frame:", i)
|
fmt.Println("Producing frame:", i)
|
||||||
|
|
||||||
// Create a buffer that can hold exactly one video RGBA frame.
|
// Create a buffer that can hold exactly one video RGBA frame.
|
||||||
buf := gst.NewBufferWithSize(videoInfo.Size())
|
buffer := gst.NewBufferWithSize(videoInfo.Size())
|
||||||
|
|
||||||
// For each frame we produce, we set the timestamp when it should be displayed
|
// For each frame we produce, we set the timestamp when it should be displayed
|
||||||
// The autovideosink will use this information to display the frame at the right time.
|
// The autovideosink will use this information to display the frame at the right time.
|
||||||
buf.SetPresentationTimestamp(time.Duration(i) * 500 * time.Millisecond)
|
buffer.SetPresentationTimestamp(time.Duration(i) * 500 * time.Millisecond)
|
||||||
|
|
||||||
// Produce an image frame for this iteration.
|
// Produce an image frame for this iteration.
|
||||||
pixels := produceImageFrame(palette[i])
|
pixels := produceImageFrame(palette[i])
|
||||||
@@ -87,10 +87,11 @@ func createPipeline() (*gst.Pipeline, error) {
|
|||||||
//
|
//
|
||||||
// There are convenience wrappers for building buffers directly from byte sequences as
|
// There are convenience wrappers for building buffers directly from byte sequences as
|
||||||
// well.
|
// well.
|
||||||
buf.Map(gst.MapWrite).WriteData(pixels)
|
buffer.Map(gst.MapWrite).WriteData(pixels)
|
||||||
|
defer buffer.Unmap()
|
||||||
|
|
||||||
// Push the buffer onto the pipeline.
|
// Push the buffer onto the pipeline.
|
||||||
self.PushBuffer(buf)
|
self.PushBuffer(buffer)
|
||||||
|
|
||||||
i++
|
i++
|
||||||
},
|
},
|
||||||
|
@@ -60,6 +60,7 @@ func padProbes(mainLoop *gst.MainLoop) error {
|
|||||||
// So mapping the buffer makes the underlying memory region accessible to us.
|
// So mapping the buffer makes the underlying memory region accessible to us.
|
||||||
// See: https://gstreamer.freedesktop.org/documentation/plugin-development/advanced/allocation.html
|
// See: https://gstreamer.freedesktop.org/documentation/plugin-development/advanced/allocation.html
|
||||||
mapInfo := buffer.Map(gst.MapRead)
|
mapInfo := buffer.Map(gst.MapRead)
|
||||||
|
defer buffer.Unmap()
|
||||||
|
|
||||||
// We know what format the data in the memory region has, since we requested
|
// 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
|
// it by setting the fakesink's caps. So what we do here is interpret the
|
||||||
|
@@ -36,6 +36,7 @@ func GetMaxBufferMemory() uint64 { return uint64(C.gst_buffer_get_max_memory())
|
|||||||
// Buffer is a go representation of a GstBuffer.
|
// Buffer is a go representation of a GstBuffer.
|
||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
ptr *C.GstBuffer
|
ptr *C.GstBuffer
|
||||||
|
mapInfo *MapInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEmptyBuffer returns a new empty buffer.
|
// NewEmptyBuffer returns a new empty buffer.
|
||||||
@@ -74,11 +75,9 @@ func NewBufferAllocate(alloc *Allocator, params *AllocationParams, size int64) *
|
|||||||
|
|
||||||
// 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)
|
gbytes := C.g_bytes_new((C.gconstpointer)(unsafe.Pointer(&b[0])), C.gsize(len(b)))
|
||||||
p := unsafe.Pointer(C.CString(str))
|
defer C.g_bytes_unref(gbytes) // gstreamer takes another ref so we don't need ours after returning
|
||||||
// memory is freed by gstreamer after building the new buffer
|
return wrapBuffer(C.gst_buffer_new_wrapped_bytes(gbytes))
|
||||||
buf := C.gst_buffer_new_wrapped((C.gpointer)(p), C.gsize(len(str)))
|
|
||||||
return wrapBuffer(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBufferFromReader returns a new buffer from the given io.Reader.
|
// NewBufferFromReader returns a new buffer from the given io.Reader.
|
||||||
@@ -144,6 +143,10 @@ func (b *Buffer) Reader() io.Reader { return bytes.NewBuffer(b.Bytes()) }
|
|||||||
// Bytes returns a byte slice of the data inside this buffer.
|
// Bytes returns a byte slice of the data inside this buffer.
|
||||||
func (b *Buffer) Bytes() []byte {
|
func (b *Buffer) Bytes() []byte {
|
||||||
mapInfo := b.Map(MapRead)
|
mapInfo := b.Map(MapRead)
|
||||||
|
if mapInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer b.Unmap()
|
||||||
return mapInfo.Bytes()
|
return mapInfo.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,20 +615,29 @@ func (b *Buffer) IterateMetaFiltered(meta *Meta, apiType glib.Type) *Meta {
|
|||||||
return wrapMeta(C.gst_buffer_iterate_meta_filtered(b.Instance(), (*C.gpointer)(&ptr), C.GType(apiType)))
|
return wrapMeta(C.gst_buffer_iterate_meta_filtered(b.Instance(), (*C.gpointer)(&ptr), C.GType(apiType)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map will map the data inside this buffer.
|
// Map will map the data inside this buffer. This function can return nil if the memory is not read or writable.
|
||||||
|
//
|
||||||
|
// Unmap the Buffer after usage.
|
||||||
func (b *Buffer) Map(flags MapFlags) *MapInfo {
|
func (b *Buffer) Map(flags MapFlags) *MapInfo {
|
||||||
var mapInfo C.GstMapInfo
|
mapInfo := C.malloc(C.sizeof_GstMapInfo)
|
||||||
C.gst_buffer_map(
|
C.gst_buffer_map(
|
||||||
(*C.GstBuffer)(b.Instance()),
|
(*C.GstBuffer)(b.Instance()),
|
||||||
(*C.GstMapInfo)(unsafe.Pointer(&mapInfo)),
|
(*C.GstMapInfo)(mapInfo),
|
||||||
C.GstMapFlags(flags),
|
C.GstMapFlags(flags),
|
||||||
)
|
)
|
||||||
return wrapMapInfo(&mapInfo, func() {
|
if mapInfo == C.NULL {
|
||||||
// This may not be necesesary
|
return nil
|
||||||
// if gobool(C.isBuffer(b.Instance())) {
|
}
|
||||||
// C.gst_buffer_unmap(b.Instance(), (*C.GstMapInfo)(unsafe.Pointer(&mapInfo)))
|
b.mapInfo = wrapMapInfo((*C.GstMapInfo)(mapInfo))
|
||||||
// }
|
return b.mapInfo
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Unmap will unmap the data inside this memory. Use this after calling Map on the buffer.
|
||||||
|
func (b *Buffer) Unmap() {
|
||||||
|
if b.mapInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
C.gst_buffer_unmap(b.Instance(), (*C.GstMapInfo)(b.mapInfo.Instance()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapRange maps the info of length merged memory blocks starting at idx in buffer.
|
// MapRange maps the info of length merged memory blocks starting at idx in buffer.
|
||||||
@@ -636,18 +648,20 @@ func (b *Buffer) Map(flags MapFlags) *MapInfo {
|
|||||||
// When the buffer is writable but the memory isn't, a writable copy will automatically be
|
// When the buffer is writable but the memory isn't, a writable copy will automatically be
|
||||||
// created and returned. The readonly copy of the buffer memory will then also be replaced with this writable copy.
|
// created and returned. The readonly copy of the buffer memory will then also be replaced with this writable copy.
|
||||||
//
|
//
|
||||||
// Unmap after usage.
|
// Unmap the Buffer after usage.
|
||||||
func (b *Buffer) MapRange(idx uint, length int, flags MapFlags) *MapInfo {
|
func (b *Buffer) MapRange(idx uint, length int, flags MapFlags) *MapInfo {
|
||||||
var mapInfo C.GstMapInfo
|
mapInfo := C.malloc(C.sizeof_GstMapInfo)
|
||||||
C.gst_buffer_map_range(
|
C.gst_buffer_map_range(
|
||||||
(*C.GstBuffer)(b.Instance()),
|
(*C.GstBuffer)(b.Instance()),
|
||||||
C.guint(idx), C.gint(length),
|
C.guint(idx), C.gint(length),
|
||||||
(*C.GstMapInfo)(unsafe.Pointer(&mapInfo)),
|
(*C.GstMapInfo)(mapInfo),
|
||||||
C.GstMapFlags(flags),
|
C.GstMapFlags(flags),
|
||||||
)
|
)
|
||||||
return wrapMapInfo(&mapInfo, func() {
|
if mapInfo == C.NULL {
|
||||||
C.gst_buffer_unmap(b.Instance(), (*C.GstMapInfo)(unsafe.Pointer(&mapInfo)))
|
return nil
|
||||||
})
|
}
|
||||||
|
b.mapInfo = wrapMapInfo((*C.GstMapInfo)(mapInfo))
|
||||||
|
return b.mapInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memset fills buf with size bytes with val starting from offset. It returns the
|
// Memset fills buf with size bytes with val starting from offset. It returns the
|
||||||
|
135
gst/gst_mapinfo.go
Normal file
135
gst/gst_mapinfo.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package gst
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "gst.go.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapInfo is a go representation of a GstMapInfo.
|
||||||
|
type MapInfo struct {
|
||||||
|
ptr *C.GstMapInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance returns the underlying GstMapInfo instance.
|
||||||
|
func (m *MapInfo) Instance() *C.GstMapInfo {
|
||||||
|
return m.ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteData writes the given sequence directly to the map's memory.
|
||||||
|
func (m *MapInfo) WriteData(data []byte) {
|
||||||
|
C.memcpy(unsafe.Pointer(m.ptr.data), unsafe.Pointer(&data[0]), C.gsize(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory returns the underlying memory object.
|
||||||
|
func (m *MapInfo) Memory() *Memory {
|
||||||
|
return wrapMemory(m.ptr.memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data returns a pointer to the raw data inside this map.
|
||||||
|
func (m *MapInfo) Data() unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(m.ptr.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags returns the flags set on this map.
|
||||||
|
func (m *MapInfo) Flags() MapFlags {
|
||||||
|
return MapFlags(m.ptr.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returrns the size of this map.
|
||||||
|
func (m *MapInfo) Size() int64 {
|
||||||
|
return int64(m.ptr.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSize returns the maximum size of this map.
|
||||||
|
func (m *MapInfo) MaxSize() int64 {
|
||||||
|
return int64(m.ptr.maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns a byte slice of the data inside this map info.
|
||||||
|
func (m *MapInfo) Bytes() []byte {
|
||||||
|
return C.GoBytes(m.Data(), (C.int)(m.Size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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])
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
@@ -2,14 +2,10 @@ package gst
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#include "gst.go.h"
|
#include "gst.go.h"
|
||||||
|
|
||||||
void writeMapData (GstMapInfo * mapInfo, gint idx, guint8 data) { mapInfo->data[idx] = data; }
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"runtime"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/glib"
|
"github.com/gotk3/gotk3/glib"
|
||||||
@@ -22,6 +18,7 @@ import (
|
|||||||
// Use the Buffer and its Map methods to interact with memory in both a read and writable way.
|
// Use the Buffer and its Map methods to interact with memory in both a read and writable way.
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
ptr *C.GstMemory
|
ptr *C.GstMemory
|
||||||
|
mapInfo *MapInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMemoryWrapped allocates a new memory block that wraps the given data.
|
// NewMemoryWrapped allocates a new memory block that wraps the given data.
|
||||||
@@ -83,151 +80,37 @@ func (m *Memory) Copy(offset, size int64) *Memory {
|
|||||||
return wrapMemory(mem)
|
return wrapMemory(mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the data inside the memory. This function can return nil if the memory is not readable.
|
// Map the data inside the memory. This function can return nil if the memory is not read or writable.
|
||||||
func (m *Memory) Map() *MapInfo {
|
//
|
||||||
var mapInfo C.GstMapInfo
|
// Unmap the Memory after usage.
|
||||||
|
func (m *Memory) Map(flags MapFlags) *MapInfo {
|
||||||
|
mapInfo := C.malloc(C.sizeof_GstMapInfo)
|
||||||
C.gst_memory_map(
|
C.gst_memory_map(
|
||||||
(*C.GstMemory)(m.Instance()),
|
(*C.GstMemory)(m.Instance()),
|
||||||
(*C.GstMapInfo)(unsafe.Pointer(&mapInfo)),
|
(*C.GstMapInfo)(mapInfo),
|
||||||
C.GST_MAP_READ,
|
C.GstMapFlags(flags),
|
||||||
)
|
)
|
||||||
return wrapMapInfo(&mapInfo, func() {
|
if mapInfo == C.NULL {
|
||||||
C.gst_memory_unmap(m.Instance(), (*C.GstMapInfo)(unsafe.Pointer(&mapInfo)))
|
return nil
|
||||||
})
|
}
|
||||||
|
m.mapInfo = wrapMapInfo((*C.GstMapInfo)(mapInfo))
|
||||||
|
return m.mapInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmap will unmap the data inside this memory. Use this after calling Map on the Memory.
|
||||||
|
func (m *Memory) Unmap() {
|
||||||
|
if m.mapInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
C.gst_memory_unmap(m.Instance(), (*C.GstMapInfo)(m.mapInfo.Instance()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes will return a byte slice of the data inside this memory if it is readable.
|
// Bytes will return a byte slice of the data inside this memory if it is readable.
|
||||||
func (m *Memory) Bytes() []byte {
|
func (m *Memory) Bytes() []byte {
|
||||||
mapInfo := m.Map()
|
mapInfo := m.Map(MapRead)
|
||||||
if mapInfo.ptr == nil {
|
if mapInfo == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
defer m.Unmap()
|
||||||
return mapInfo.Bytes()
|
return mapInfo.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapInfo is a go representation of a GstMapInfo.
|
|
||||||
type MapInfo struct {
|
|
||||||
ptr *C.GstMapInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory returns the underlying memory object.
|
|
||||||
func (m *MapInfo) Memory() *Memory {
|
|
||||||
return wrapMemory(m.ptr.memory)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data returns a pointer to the raw data inside this map.
|
|
||||||
func (m *MapInfo) Data() unsafe.Pointer {
|
|
||||||
return unsafe.Pointer(m.ptr.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flags returns the flags set on this map.
|
|
||||||
func (m *MapInfo) Flags() MapFlags {
|
|
||||||
return MapFlags(m.ptr.flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returrns the size of this map.
|
|
||||||
func (m *MapInfo) Size() int64 {
|
|
||||||
return int64(m.ptr.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxSize returns the maximum size of this map.
|
|
||||||
func (m *MapInfo) MaxSize() int64 {
|
|
||||||
return int64(m.ptr.maxsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns a byte slice of the data inside this map info.
|
|
||||||
func (m *MapInfo) Bytes() []byte {
|
|
||||||
return C.GoBytes(m.Data(), (C.int)(m.Size()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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])
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
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]))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteData writes the given values directly to the map's memory.
|
|
||||||
func (m *MapInfo) WriteData(data []uint8) {
|
|
||||||
for i, x := range data {
|
|
||||||
C.writeMapData(m.ptr, C.gint(i), C.guint8(x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrapMapInfo(mapInfo *C.GstMapInfo, unmapFunc func()) *MapInfo {
|
|
||||||
info := &MapInfo{ptr: mapInfo}
|
|
||||||
runtime.SetFinalizer(info, func(_ *MapInfo) { unmapFunc() })
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
@@ -169,6 +169,7 @@ func wrapEvent(ev *C.GstEvent) *Event { return &Event{ptr: e
|
|||||||
func wrapGhostPad(obj *glib.Object) *GhostPad { return &GhostPad{wrapProxyPad(obj)} }
|
func wrapGhostPad(obj *glib.Object) *GhostPad { return &GhostPad{wrapProxyPad(obj)} }
|
||||||
func wrapMainContext(ctx *C.GMainContext) *MainContext { return &MainContext{ptr: ctx} }
|
func wrapMainContext(ctx *C.GMainContext) *MainContext { return &MainContext{ptr: ctx} }
|
||||||
func wrapMainLoop(loop *C.GMainLoop) *MainLoop { return &MainLoop{ptr: loop} }
|
func wrapMainLoop(loop *C.GMainLoop) *MainLoop { return &MainLoop{ptr: loop} }
|
||||||
|
func wrapMapInfo(mapInfo *C.GstMapInfo) *MapInfo { return &MapInfo{ptr: mapInfo} }
|
||||||
func wrapMemory(mem *C.GstMemory) *Memory { return &Memory{ptr: mem} }
|
func wrapMemory(mem *C.GstMemory) *Memory { return &Memory{ptr: mem} }
|
||||||
func wrapMessage(msg *C.GstMessage) *Message { return &Message{msg: msg} }
|
func wrapMessage(msg *C.GstMessage) *Message { return &Message{msg: msg} }
|
||||||
func wrapMeta(meta *C.GstMeta) *Meta { return &Meta{ptr: meta} }
|
func wrapMeta(meta *C.GstMeta) *Meta { return &Meta{ptr: meta} }
|
||||||
|
Reference in New Issue
Block a user