-
Notifications
You must be signed in to change notification settings - Fork 50
/
gst_buffer.go
748 lines (659 loc) · 28 KB
/
gst_buffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
package gst
/*
#include "gst.go.h"
extern void goGDestroyNotifyFunc (gpointer data);
extern gboolean goBufferMetaForEachCb (GstBuffer * buffer, GstMeta ** meta, gpointer user_data);
void cgoDestroyNotifyFunc (gpointer data) {
goGDestroyNotifyFunc(data);
}
gboolean cgoBufferMetaForEachCb (GstBuffer * buffer, GstMeta ** meta, gpointer user_data)
{
return goBufferMetaForEachCb(buffer, meta, user_data);
}
gboolean isBuffer (GstBuffer * buffer) { return GST_IS_BUFFER(buffer); }
*/
import "C"
import (
"bytes"
"io"
"runtime"
"unsafe"
"github.com/go-gst/go-glib/glib"
gopointer "github.com/mattn/go-pointer"
)
// GetMaxBufferMemory returns the maximum amount of memory a buffer can hold.
func GetMaxBufferMemory() uint64 { return uint64(C.gst_buffer_get_max_memory()) }
// Buffer is a go representation of a GstBuffer.
type Buffer struct {
ptr *C.GstBuffer
mapInfo *MapInfo
}
// FromGstBufferUnsafeNone wraps the given buffer, sinking any floating references, and places
// a finalizer on the wrapped Buffer.
func FromGstBufferUnsafeNone(buf unsafe.Pointer) *Buffer {
if buf == nil {
return nil
}
wrapped := ToGstBuffer(buf)
wrapped.Ref()
runtime.SetFinalizer(wrapped, (*Buffer).Unref)
return wrapped
}
// FromGstBufferUnsafeFull wraps the given buffer without taking an additional reference.
func FromGstBufferUnsafeFull(buf unsafe.Pointer) *Buffer {
if buf == nil {
return nil
}
wrapped := ToGstBuffer(buf)
runtime.SetFinalizer(wrapped, (*Buffer).Unref)
return wrapped
}
// ToGstBuffer converts the given pointer into a Buffer without affecting the ref count or
// placing finalizers.
func ToGstBuffer(buf unsafe.Pointer) *Buffer {
return wrapBuffer((*C.GstBuffer)(buf))
}
// NewEmptyBuffer returns a new empty buffer.
func NewEmptyBuffer() *Buffer {
return FromGstBufferUnsafeFull(unsafe.Pointer(C.gst_buffer_new()))
}
// NewBufferWithSize is a convenience wrapped for NewBufferrAllocate with the default allocator
// and parameters.
func NewBufferWithSize(size int64) *Buffer {
return NewBufferAllocate(nil, nil, size)
}
// 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()
}
var gstparams *C.GstAllocationParams
if params != nil {
gstparams = params.Instance()
}
buf := C.gst_buffer_new_allocate(gstalloc, C.gsize(size), gstparams)
if buf == nil {
return nil
}
return FromGstBufferUnsafeFull(unsafe.Pointer(buf))
}
// NewBufferFromBytes returns a new buffer from the given byte slice.
func NewBufferFromBytes(b []byte) *Buffer {
gbytes := C.g_bytes_new((C.gconstpointer)(unsafe.Pointer(&b[0])), C.gsize(len(b)))
defer C.g_bytes_unref(gbytes)
return FromGstBufferUnsafeFull(unsafe.Pointer(C.gst_buffer_new_wrapped_bytes(gbytes)))
}
// NewBufferFromReader returns a new buffer from the given io.Reader.
func NewBufferFromReader(rdr io.Reader) (*Buffer, error) {
out, err := io.ReadAll(rdr)
if err != nil {
return nil, err
}
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 FromGstBufferUnsafeFull(unsafe.Pointer(buf))
}
// Instance returns the underlying GstBuffer instance.
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.
func (b *Buffer) Reader() io.Reader { return bytes.NewBuffer(b.Bytes()) }
// Bytes returns a byte slice of the data inside this buffer.
func (b *Buffer) Bytes() []byte {
mapInfo := b.Map(MapRead)
if mapInfo == nil {
return nil
}
defer b.Unmap()
return mapInfo.Bytes()
}
// PresentationTimestamp returns the presentation timestamp of the buffer, or a negative duration
// if not known or relevant. This value contains the timestamp when the media should be
// presented to the user.
func (b *Buffer) PresentationTimestamp() ClockTime {
pts := b.Instance().pts
return ClockTime(pts)
}
// SetPresentationTimestamp sets the presentation timestamp on the buffer.
func (b *Buffer) SetPresentationTimestamp(dur ClockTime) {
ins := b.Instance()
ins.pts = C.GstClockTime(dur)
}
// DecodingTimestamp returns the decoding timestamp of the buffer, or a negative duration if not known
// or relevant. This value contains the timestamp when the media should be processed.
func (b *Buffer) DecodingTimestamp() ClockTime {
dts := b.Instance().dts
return ClockTime(dts)
}
// Duration returns the length of the data inside this buffer, or a negative duration if not known
// or relevant.
func (b *Buffer) Duration() ClockTime {
dur := b.Instance().duration
return ClockTime(dur)
}
// SetDuration sets the duration on the buffer.
func (b *Buffer) SetDuration(dur ClockTime) {
ins := b.Instance()
ins.duration = C.GstClockTime(dur)
}
// Offset returns a media specific offset for the buffer data. For video frames, this is the frame
// number of this buffer. For audio samples, this is the offset of the first sample in this buffer.
// For file data or compressed data this is the byte offset of the first byte in this buffer.
func (b *Buffer) Offset() int64 { return int64(b.Instance().offset) }
// OffsetEnd returns the last offset contained in this buffer. It has the same format as Offset.
func (b *Buffer) OffsetEnd() int64 { return int64(b.Instance().offset_end) }
// 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("MyObjectType"), "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)
}
// ParentBufferMeta is a go representation of a GstParentBufferMeta
type ParentBufferMeta struct {
Parent *Meta
Buffer *Buffer
}
// AddParentMeta adds a ParentBufferMeta to this buffer that holds a parent reference
// on the given buffer until the it is freed.
func (b *Buffer) AddParentMeta(buf *Buffer) *ParentBufferMeta {
meta := C.gst_buffer_add_parent_buffer_meta(b.Instance(), buf.Instance())
return &ParentBufferMeta{
Parent: wrapMeta(&meta.parent),
Buffer: wrapBuffer(meta.buffer),
}
}
// AddProtectionMeta attaches ProtectionMeta to this buffer. The structure contains
// cryptographic information relating to the sample contained in the buffer. This
// function takes ownership of the structure.
func (b *Buffer) AddProtectionMeta(info *Structure) *ProtectionMeta {
meta := C.gst_buffer_add_protection_meta(b.Instance(), info.Instance())
return &ProtectionMeta{
Meta: wrapMeta(&meta.meta),
Info: wrapStructure(meta.info),
}
}
// ReferenceTimestampMeta is a go representation of a GstReferenceTimestampMeta.
type ReferenceTimestampMeta struct {
Parent *Meta
Reference *Caps
Timestamp, Duration ClockTime
}
// AddReferenceTimestampMeta adds a ReferenceTimestampMeta to this buffer that holds a
// timestamp and optional duration (specify -1 to omit) based on a specific timestamp reference.
//
// See the documentation of GstReferenceTimestampMeta for details.
// https://gstreamer.freedesktop.org/documentation/gstreamer/gstbuffer.html?gi-language=c#GstReferenceTimestampMeta
func (b *Buffer) AddReferenceTimestampMeta(ref *Caps, timestamp, duration ClockTime) *ReferenceTimestampMeta {
meta := C.gst_buffer_add_reference_timestamp_meta(b.Instance(), ref.Instance(), C.GstClockTime(timestamp), C.GstClockTime(duration))
if meta == nil {
return nil
}
return &ReferenceTimestampMeta{
Parent: wrapMeta(&meta.parent),
Reference: wrapCaps(meta.reference),
Timestamp: ClockTime(meta.timestamp),
Duration: ClockTime(meta.duration),
}
}
// Append will append all the memory from the given buffer to this one. The result buffer will
// contain a concatenation of the memory of the two buffers.
func (b *Buffer) Append(buf *Buffer) *Buffer {
return FromGstBufferUnsafeFull(unsafe.Pointer(C.gst_buffer_append(b.Ref().Instance(), buf.Ref().Instance())))
}
// AppendMemory append the memory block to this buffer. This function takes ownership of
// the memory and thus doesn't increase its refcount.
//
// This function is identical to InsertMemory with an index of -1.
func (b *Buffer) AppendMemory(mem *Memory) {
C.gst_buffer_append_memory(b.Instance(), mem.Ref().Instance())
}
// AppendRegion will append size bytes at offset from the given buffer to this one. The result
// buffer will contain a concatenation of the memory of this buffer and the requested region of
// the one provided.
func (b *Buffer) AppendRegion(buf *Buffer, offset, size int64) *Buffer {
newbuf := C.gst_buffer_append_region(b.Ref().Instance(), buf.Ref().Instance(), C.gssize(offset), C.gssize(size))
return FromGstBufferUnsafeFull(unsafe.Pointer(newbuf))
}
// Copy creates a copy of this buffer. This will only copy the buffer's data to a newly allocated
// Memory if needed (if the type of memory requires it), otherwise the underlying data is just referenced.
// Check DeepCopy if you want to force the data to be copied to newly allocated Memory.
func (b *Buffer) Copy() *Buffer {
buf := C.gst_buffer_copy(b.Instance())
return FromGstBufferUnsafeFull(unsafe.Pointer(buf))
}
// DeepCopy creates a copy of the given buffer. This will make a newly allocated copy of the data
// the source buffer contains.
func (b *Buffer) DeepCopy() *Buffer {
buf := C.gst_buffer_copy_deep(b.Instance())
return FromGstBufferUnsafeFull(unsafe.Pointer(buf))
}
// CopyInto copies the information from this buffer into the given one. If the given buffer already
// contains memory and flags contains BufferCopyMemory, the memory from this one will be appended to
// that provided.
//
// Flags indicate which fields will be copied. Offset and size dictate from where and how much memory
// is copied. If size is -1 then all data is copied. The function returns true if the copy was successful.
func (b *Buffer) CopyInto(dest *Buffer, flags BufferCopyFlags, offset, size int64) bool {
ok := C.gst_buffer_copy_into(
dest.Instance(),
b.Instance(),
C.GstBufferCopyFlags(flags),
C.gsize(offset),
C.gsize(size),
)
return gobool(ok)
}
// CopyRegion creates a sub-buffer from this one at offset and size. This sub-buffer uses the actual memory
// space of the parent buffer. This function will copy the offset and timestamp fields when the offset is 0.
// If not, they will be set to ClockTimeNone.
//
// If offset equals 0 and size equals the total size of buffer, the duration and offset end fields are also
// copied. If not they will be set to ClockTimeNone.
func (b *Buffer) CopyRegion(flags BufferCopyFlags, offset, size int64) *Buffer {
newbuf := C.gst_buffer_copy_region(
b.Instance(),
C.GstBufferCopyFlags(flags),
C.gsize(offset),
C.gsize(size),
)
return wrapBuffer(newbuf)
}
// Extract extracts size bytes starting from offset in this buffer. The data extracted may be lower
// than the actual size if the buffer did not contain enough data.
func (b *Buffer) Extract(offset, size int64) []byte {
dest := C.malloc(C.sizeof_char * C.gsize(size))
defer C.free(dest)
C.gst_buffer_extract(b.Instance(), C.gsize(offset), (C.gpointer)(unsafe.Pointer(dest)), C.gsize(size))
return C.GoBytes(dest, C.int(size))
}
// FillBytes adds the given byte slice to the buffer at the given offset. The return value reflects the amount
// of data added to the buffer.
func (b *Buffer) FillBytes(offset int64, data []byte) int64 {
gbytes := C.g_bytes_new((C.gconstpointer)(unsafe.Pointer(&data[0])), C.gsize(len(data)))
defer C.g_bytes_unref(gbytes)
var size C.gsize
gdata := C.g_bytes_get_data(gbytes, &size)
if gdata == nil {
return 0
}
return int64(C.gst_buffer_fill(b.Instance(), C.gsize(offset), gdata, size))
}
// FindMemory looks for the memory blocks that span size bytes starting from offset in buffer. Size can be -1
// to retrieve all the memory blocks.
//
// Index will contain the index of the first memory block where the byte for offset can be found and length
// contains the number of memory blocks containing the size remaining bytes. Skip contains the number of bytes
// to skip in the memory block at index to get to the byte for offset. All values will be 0 if the memory blocks
// could not be read.
func (b *Buffer) FindMemory(offset, size int64) (index, length uint, skip int64) {
var gindex, glength C.uint
var gskip C.gsize
ok := C.gst_buffer_find_memory(b.Instance(), C.gsize(offset), C.gsize(size), &gindex, &glength, &gskip)
if !gobool(ok) {
return
}
return uint(gindex), uint(glength), int64(gskip)
}
// ForEachMeta calls the given function for each Meta in this buffer.
//
// The function can modify the passed meta pointer or its contents. The return value defines if this function continues
// or if the remaining metadata items in the buffer should be skipped.
func (b *Buffer) ForEachMeta(f func(meta *Meta) bool) bool {
fPtr := gopointer.Save(f)
defer gopointer.Unref(fPtr)
return gobool(C.gst_buffer_foreach_meta(
b.Instance(),
C.GstBufferForeachMetaFunc(C.cgoBufferMetaForEachCb),
(C.gpointer)(unsafe.Pointer(fPtr)),
))
}
// GetAllMemory retrieves all the memory inside this buffer.
func (b *Buffer) GetAllMemory() *Memory {
mem := C.gst_buffer_get_all_memory(b.Instance())
if mem == nil {
return nil
}
return FromGstMemoryUnsafeFull(unsafe.Pointer(mem))
}
// GetFlags returns the flags on this buffer.
func (b *Buffer) GetFlags() BufferFlags {
return BufferFlags(C.gst_buffer_get_flags(b.Instance()))
}
// GetMemory retrieves the memory block at the given index in the buffer.
func (b *Buffer) GetMemory(idx uint) *Memory {
mem := C.gst_buffer_get_memory(b.Instance(), C.guint(idx))
if mem == nil {
return nil
}
return FromGstMemoryUnsafeFull(unsafe.Pointer(mem))
}
// GetMemoryRange retrieves length memory blocks in buffer starting at idx. The memory blocks
// will be merged into one large Memory. If length is -1, all memory starting from idx is merged.
func (b *Buffer) GetMemoryRange(idx uint, length int) *Memory {
mem := C.gst_buffer_get_memory_range(b.Instance(), C.guint(idx), C.gint(length))
if mem == nil {
return nil
}
return FromGstMemoryUnsafeFull(unsafe.Pointer(mem))
}
// GetMeta retrieves the metadata for the given api on buffer. When there is no such metadata,
// nil is returned. If multiple metadata with the given api are attached to this buffer only the
// first one is returned. To handle multiple metadata with a given API use ForEachMeta instead
// and check the type.
func (b *Buffer) GetMeta(api glib.Type) *Meta {
meta := C.gst_buffer_get_meta(b.Instance(), C.GType(api))
if meta == nil {
return nil
}
return wrapMeta(meta)
}
// GetNumMetas returns the number of metas for the given api type on the buffer.
func (b *Buffer) GetNumMetas(api glib.Type) uint {
return uint(C.gst_buffer_get_n_meta(b.Instance(), C.GType(api)))
}
// GetReferenceTimestampMeta finds the first ReferenceTimestampMeta on the buffer that conforms to
// reference. Conformance is tested by checking if the meta's reference is a subset of reference.
//
// Buffers can contain multiple ReferenceTimestampMeta metadata items.
func (b *Buffer) GetReferenceTimestampMeta(caps *Caps) *ReferenceTimestampMeta {
var meta *C.GstReferenceTimestampMeta
if caps == nil {
meta = C.gst_buffer_get_reference_timestamp_meta(b.Instance(), nil)
} else {
meta = C.gst_buffer_get_reference_timestamp_meta(b.Instance(), caps.Instance())
}
if meta == nil {
return nil
}
refMeta := &ReferenceTimestampMeta{
Parent: wrapMeta(&meta.parent),
Timestamp: ClockTime(meta.timestamp),
Duration: ClockTime(meta.duration),
}
if meta.reference != nil {
refMeta.Reference = wrapCaps(meta.reference)
}
return refMeta
}
// GetSize retrieves the number of Memory blocks in the bffer.
func (b *Buffer) GetSize() int64 {
return int64(C.gst_buffer_get_size(b.Instance()))
}
// GetSizes will retrieve the size of the buffer, the offset of the first memory block in the buffer,
// and the sum of the size of the buffer, the offset, and any padding. These values can be used to
// resize the buffer with Resize.
func (b *Buffer) GetSizes() (size, offset, maxsize int64) {
var goffset, gmaxsize C.gsize
gsize := C.gst_buffer_get_sizes(b.Instance(), &goffset, &gmaxsize)
return int64(gsize), int64(goffset), int64(gmaxsize)
}
// GetSizesRange will get the total size of length memory blocks stating from idx in buffer.
//
// Offset will contain the offset of the data in the memory block in buffer at idx and maxsize will
// contain the sum of the size and offset and the amount of extra padding on the memory block at
// idx + length -1. Offset and maxsize can be used to resize the buffer memory blocks with ResizeRange.
func (b *Buffer) GetSizesRange(idx uint, length int) (offset, maxsize int64) {
var goffset, gmaxsize C.gsize
C.gst_buffer_get_sizes_range(b.Instance(), C.guint(idx), C.gint(length), &goffset, &gmaxsize)
return int64(goffset), int64(gmaxsize)
}
// HasFlags returns true if this Buffer has the given BufferFlags.
func (b *Buffer) HasFlags(flags BufferFlags) bool {
return gobool(C.gst_buffer_has_flags(b.Instance(), C.GstBufferFlags(flags)))
}
// InsertMemory insert the memory block to the buffer at idx. This function takes ownership of the Memory
// and thus doesn't increase its refcount.
//
// Only the value from GetMaxBufferMemory can be added to a buffer. If more memory is added, existing memory
// blocks will automatically be merged to make room for the new memory.
func (b *Buffer) InsertMemory(mem *Memory, idx int) {
C.gst_buffer_insert_memory(b.Instance(), C.gint(idx), mem.Ref().Instance())
}
// IsAllMemoryWritable checks if all memory blocks in buffer are writable.
//
// Note that this function does not check if buffer is writable, use IsWritable to check that if needed.
func (b *Buffer) IsAllMemoryWritable() bool {
return gobool(C.gst_buffer_is_all_memory_writable(b.Instance()))
}
// IsMemoryRangeWritable checks if length memory blocks in the buffer starting from idx are writable.
//
// Length can be -1 to check all the memory blocks after idx.
//
// Note that this function does not check if buffer is writable, use IsWritable to check that if needed.
func (b *Buffer) IsMemoryRangeWritable(idx uint, length int) bool {
return gobool(C.gst_buffer_is_memory_range_writable(b.Instance(), C.guint(idx), C.gint(length)))
}
// IsWritable returns true if this buffer is writable.
func (b *Buffer) IsWritable() bool {
return gobool(C.bufferIsWritable(b.Instance()))
}
// MakeWritable returns a writable copy of this buffer. If the source buffer is already writable,
// this will simply return the same buffer.
//
// Use this function to ensure that a buffer can be safely modified before making changes to it,
// including changing the metadata such as PTS/DTS.
//
// If the reference count of the source buffer buf is exactly one, the caller is the sole owner and
// this function will return the buffer object unchanged.
//
// If there is more than one reference on the object, a copy will be made using gst_buffer_copy. The passed-in buf
// will be unreffed in that case, and the caller will now own a reference to the new returned buffer object. Note that
// this just copies the buffer structure itself, the underlying memory is not copied if it can be shared amongst
// multiple buffers.
//
// In short, this function unrefs the buf in the argument and refs the buffer that it returns. Don't access the argument
// after calling this function unless you have an additional reference to it.
func (b *Buffer) MakeWritable() *Buffer {
return wrapBuffer(C.makeBufferWritable(b.Instance()))
}
// IterateMeta retrieves the next Meta after the given one. If state points to nil, the first Meta is returned.
func (b *Buffer) IterateMeta(meta *Meta) *Meta {
ptr := unsafe.Pointer(meta.Instance())
return wrapMeta(C.gst_buffer_iterate_meta(b.Instance(), (*C.gpointer)(&ptr)))
}
// IterateMetaFiltered is similar to IterateMeta except it will filter on the api type.
func (b *Buffer) IterateMetaFiltered(meta *Meta, apiType glib.Type) *Meta {
ptr := unsafe.Pointer(meta.Instance())
return wrapMeta(C.gst_buffer_iterate_meta_filtered(b.Instance(), (*C.gpointer)(&ptr), C.GType(apiType)))
}
// Map will map the data inside this buffer. This function can return nil if the memory is not read or writable.
// It is safe to call this function multiple times on a single Buffer, however it will retain the flags
// used when mapping the first time. To change between read and write access first unmap and then remap the
// buffer with the appropriate flags, or map initially with both read/write access.
//
// Unmap the Buffer after usage.
func (b *Buffer) Map(flags MapFlags) *MapInfo {
if b.mapInfo != nil {
return b.mapInfo
}
var mapInfo C.GstMapInfo
C.gst_buffer_map(
(*C.GstBuffer)(b.Instance()),
(*C.GstMapInfo)(&mapInfo),
C.GstMapFlags(flags),
)
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()))
b.mapInfo = nil
}
// MapRange maps the info of length merged memory blocks starting at idx in buffer.
// When length is -1, all memory blocks starting from idx are merged and mapped.
//
// Flags describe the desired access of the memory. When flags is MapWrite, buffer should be writable (as returned from IsWritable).
//
// 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.
//
// Unmap the Buffer after usage.
func (b *Buffer) MapRange(idx uint, length int, flags MapFlags) *MapInfo {
if b.mapInfo != nil {
return b.mapInfo
}
var mapInfo C.GstMapInfo
C.gst_buffer_map_range(
(*C.GstBuffer)(b.Instance()),
C.guint(idx), C.gint(length),
(*C.GstMapInfo)(&mapInfo),
C.GstMapFlags(flags),
)
b.mapInfo = wrapMapInfo((*C.GstMapInfo)(&mapInfo))
return b.mapInfo
}
// Memset fills buf with size bytes with val starting from offset. It returns the
// size written to the buffer.
func (b *Buffer) Memset(offset int64, val uint8, size int64) int64 {
return int64(C.gst_buffer_memset(b.Instance(), C.gsize(offset), C.guint8(val), C.gsize(size)))
}
// NumMemoryBlocks returns the number of memory blocks this buffer has.
func (b *Buffer) NumMemoryBlocks() uint { return uint(C.gst_buffer_n_memory(b.Instance())) }
// PeekMemory gets the memory block at idx in buffer. The memory block stays valid until the
// memory block is removed, replaced, or merged. Typically with any call that modifies the memory in buffer.
func (b *Buffer) PeekMemory(idx uint) *Memory {
mem := C.gst_buffer_peek_memory(b.Instance(), C.guint(idx))
if mem == nil {
return nil
}
return FromGstMemoryUnsafeNone(unsafe.Pointer(mem))
}
// PrependMemory prepends the memory block mem to this buffer. This function takes ownership of
// mem and thus doesn't increase its refcount.
//
// This function is identical to InsertMemory with an index of 0.
func (b *Buffer) PrependMemory(mem *Memory) {
C.gst_buffer_prepend_memory(b.Instance(), mem.Ref().Instance())
}
// RemoveAllMemory removes all memory blocks in the buffer.
func (b *Buffer) RemoveAllMemory() { C.gst_buffer_remove_all_memory(b.Instance()) }
// RemoveMemoryAt removes the memory block at the given index.
func (b *Buffer) RemoveMemoryAt(idx uint) { C.gst_buffer_remove_memory(b.Instance(), C.guint(idx)) }
// RemoveMemoryRange removes length memory blocks in buffer starting from idx.
//
// Length can be -1, in which case all memory starting from idx is removed.
func (b *Buffer) RemoveMemoryRange(idx uint, length int) {
C.gst_buffer_remove_memory_range(b.Instance(), C.guint(idx), C.gint(length))
}
// RemoveMeta removes the given metadata from the buffer.
func (b *Buffer) RemoveMeta(meta *Meta) bool {
return gobool(C.gst_buffer_remove_meta(b.Instance(), meta.Instance()))
}
// ReplaceAllMemory replaces all the memory in this buffer with that provided.
func (b *Buffer) ReplaceAllMemory(mem *Memory) {
C.gst_buffer_replace_all_memory(b.Instance(), mem.Ref().Instance())
}
// ReplaceMemory replaces the memory at the given index with the given memory.
func (b *Buffer) ReplaceMemory(mem *Memory, idx uint) {
C.gst_buffer_replace_memory(b.Instance(), C.guint(idx), mem.Ref().Instance())
}
// ReplaceMemoryRange replaces length memory blocks in the buffer starting at idx with
// the given memory.
//
// If length is -1, all memory starting from idx will be removed and replaced.
//
// The buffer should be writable.
func (b *Buffer) ReplaceMemoryRange(idx uint, length int, mem *Memory) {
C.gst_buffer_replace_memory_range(b.Instance(), C.guint(idx), C.gint(length), mem.Ref().Instance())
}
// Resize sets the offset and total size of the memory blocks in this buffer.
func (b *Buffer) Resize(offset, size int64) {
C.gst_buffer_resize(b.Instance(), C.gssize(offset), C.gssize(size))
}
// ResizeRange sets the total size of the length memory blocks starting at idx in this buffer.
func (b *Buffer) ResizeRange(idx uint, length int, offset, size int64) bool {
return gobool(C.gst_buffer_resize_range(
b.Instance(),
C.guint(idx),
C.gint(length),
C.gssize(offset),
C.gssize(size),
))
}
// SetFlags sets one or more buffer flags on the buffer.
func (b *Buffer) SetFlags(flags BufferFlags) bool {
return gobool(C.gst_buffer_set_flags(b.Instance(), C.GstBufferFlags(flags)))
}
// SetSize sets the total size of the memory blocks in buffer.
func (b *Buffer) SetSize(size int64) {
C.gst_buffer_set_size(b.Instance(), C.gssize(size))
}
// UnsetFlags removes one or more flags from the buffer.
func (b *Buffer) UnsetFlags(flags BufferFlags) bool {
return gobool(C.gst_buffer_unset_flags(b.Instance(), C.GstBufferFlags(flags)))
}