mirror of
https://github.com/go-gst/go-gst.git
synced 2025-09-27 04:15:56 +08:00
221 lines
8.7 KiB
Go
221 lines
8.7 KiB
Go
package app
|
||
|
||
/*
|
||
#include "gst.go.h"
|
||
|
||
extern void goAppGDestroyNotifyFunc (gpointer user_data);
|
||
|
||
extern void goNeedDataCb (GstAppSrc *src, guint length, gpointer user_data);
|
||
extern void goEnoughDataDb (GstAppSrc *src, gpointer user_data);
|
||
extern gboolean goSeekDataCb (GstAppSrc *src, guint64 offset, gpointer user_data);
|
||
|
||
void cgoSrcGDestroyNotifyFunc (gpointer user_data) { goAppGDestroyNotifyFunc(user_data); }
|
||
|
||
void cgoNeedDataCb (GstAppSrc *src, guint length, gpointer user_data) { goNeedDataCb(src, length, user_data); }
|
||
void cgoEnoughDataCb (GstAppSrc *src, gpointer user_data) { goEnoughDataDb(src, user_data); }
|
||
gboolean cgoSeekDataCb (GstAppSrc *src, guint64 offset, gpointer user_data) { return goSeekDataCb(src, offset, user_data); }
|
||
|
||
*/
|
||
import "C"
|
||
import (
|
||
"unsafe"
|
||
|
||
"github.com/go-gst/go-gst/gst"
|
||
"github.com/go-gst/go-gst/gst/base"
|
||
gopointer "github.com/mattn/go-pointer"
|
||
)
|
||
|
||
// SourceCallbacks represents callbacks to configure on an AppSource.
|
||
type SourceCallbacks struct {
|
||
NeedDataFunc func(src *Source, length uint)
|
||
EnoughDataFunc func(src *Source)
|
||
SeekDataFunc func(src *Source, offset uint64) bool
|
||
}
|
||
|
||
// StreamType casts GstAppStreamType
|
||
type StreamType int
|
||
|
||
// Type castings
|
||
const (
|
||
AppStreamTypeStream StreamType = C.GST_APP_STREAM_TYPE_STREAM // (0) – No seeking is supported in the stream, such as a live stream.
|
||
AppStreamTypeSeekable StreamType = C.GST_APP_STREAM_TYPE_SEEKABLE // (1) – The stream is seekable but seeking might not be very fast, such as data from a webserver.
|
||
AppStreamTypeRandomAccess StreamType = C.GST_APP_STREAM_TYPE_RANDOM_ACCESS // (2) – The stream is seekable and seeking is fast, such as in a local file.
|
||
)
|
||
|
||
// Source wraps an Element made with the appsrc plugin with additional methods for pushing samples.
|
||
type Source struct{ *base.GstBaseSrc }
|
||
|
||
// NewAppSrc returns a new AppSrc element.
|
||
func NewAppSrc() (*Source, error) {
|
||
elem, err := gst.NewElement("appsrc")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return wrapAppSrc(elem), nil
|
||
}
|
||
|
||
// SrcFromElement checks if the given element is an appsrc and if so returns
|
||
// a Source interace.
|
||
func SrcFromElement(elem *gst.Element) *Source {
|
||
if appSrc := C.toGstAppSrc(elem.Unsafe()); appSrc != nil {
|
||
return wrapAppSrc(elem)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Instance returns the native GstAppSink instance.
|
||
func (a *Source) Instance() *C.GstAppSrc { return C.toGstAppSrc(a.Unsafe()) }
|
||
|
||
// EndStream signals to the app source that the stream has ended after the last queued
|
||
// buffer.
|
||
func (a *Source) EndStream() gst.FlowReturn {
|
||
ret := C.gst_app_src_end_of_stream((*C.GstAppSrc)(a.Instance()))
|
||
return gst.FlowReturn(ret)
|
||
}
|
||
|
||
// GetCaps gets the configures caps on the app src.
|
||
func (a *Source) GetCaps() *gst.Caps {
|
||
caps := C.gst_app_src_get_caps(a.Instance())
|
||
if caps == nil {
|
||
return nil
|
||
}
|
||
return gst.FromGstCapsUnsafeFull(unsafe.Pointer(caps))
|
||
}
|
||
|
||
// GetCurrentLevelBytes gets the number of currently queued bytes inside appsrc.
|
||
func (a *Source) GetCurrentLevelBytes() uint64 {
|
||
return uint64(C.gst_app_src_get_current_level_bytes(a.Instance()))
|
||
}
|
||
|
||
var gstClockTimeNone C.GstClockTime = 0xffffffffffffffff
|
||
|
||
// GetDuration gets the duration of the stream in nanoseconds. A negative value means that the duration is not known.
|
||
func (a *Source) GetDuration() gst.ClockTime {
|
||
dur := C.gst_app_src_get_duration(a.Instance())
|
||
|
||
return gst.ClockTime(dur)
|
||
}
|
||
|
||
// GetEmitSignals checks if appsrc will emit the "new-preroll" and "new-buffer" signals.
|
||
func (a *Source) GetEmitSignals() bool {
|
||
return gobool(C.gst_app_src_get_emit_signals(a.Instance()))
|
||
}
|
||
|
||
// GetLatency retrieves the min and max latencies in min and max respectively.
|
||
func (a *Source) GetLatency() (min, max uint64) {
|
||
var gmin, gmax C.guint64
|
||
C.gst_app_src_get_latency(a.Instance(), &gmin, &gmax)
|
||
return uint64(gmin), uint64(gmax)
|
||
}
|
||
|
||
// GetMaxBytes gets the maximum amount of bytes that can be queued in appsrc.
|
||
func (a *Source) GetMaxBytes() uint64 {
|
||
return uint64(C.gst_app_src_get_max_bytes(a.Instance()))
|
||
}
|
||
|
||
// GetSize gets the size of the stream in bytes. A value of -1 means that the size is not known.
|
||
func (a *Source) GetSize() int64 {
|
||
return int64(C.gst_app_src_get_size(a.Instance()))
|
||
}
|
||
|
||
// GetStreamType gets the stream type. Control the stream type of appsrc with SetStreamType.
|
||
func (a *Source) GetStreamType() StreamType {
|
||
return StreamType(C.gst_app_src_get_stream_type(a.Instance()))
|
||
}
|
||
|
||
// PushBuffer pushes a buffer to the appsrc. Currently by default this will block
|
||
// until the source is ready to accept the buffer.
|
||
func (a *Source) PushBuffer(buf *gst.Buffer) gst.FlowReturn {
|
||
ret := C.gst_app_src_push_buffer(
|
||
(*C.GstAppSrc)(a.Instance()),
|
||
(*C.GstBuffer)(unsafe.Pointer(buf.Ref().Instance())),
|
||
)
|
||
return gst.FlowReturn(ret)
|
||
}
|
||
|
||
// PushBufferList adds a buffer list to the queue of buffers and buffer lists that the appsrc element will push
|
||
// to its source pad. This function takes ownership of buffer_list.
|
||
//
|
||
// When the block property is TRUE, this function can block until free space becomes available in the queue.
|
||
func (a *Source) PushBufferList(bufList *gst.BufferList) gst.FlowReturn {
|
||
return gst.FlowReturn(C.gst_app_src_push_buffer_list(
|
||
a.Instance(), (*C.GstBufferList)(unsafe.Pointer(bufList.Ref().Instance())),
|
||
))
|
||
}
|
||
|
||
// PushSample Extract a buffer from the provided sample and adds it to the queue of buffers that the appsrc element will
|
||
// push to its source pad. Any previous caps that were set on appsrc will be replaced by the caps associated with the
|
||
// sample if not equal.
|
||
//
|
||
// This function does not take ownership of the sample so the sample needs to be unreffed after calling this function.
|
||
//
|
||
// When the block property is TRUE, this function can block until free space becomes available in the queue.
|
||
func (a *Source) PushSample(sample *gst.Sample) gst.FlowReturn {
|
||
return gst.FlowReturn(C.gst_app_src_push_sample(
|
||
a.Instance(), (*C.GstSample)(unsafe.Pointer(sample.Instance())),
|
||
))
|
||
}
|
||
|
||
// SetCallbacks sets callbacks which will be executed when data is needed, enough data has been collected or when a seek
|
||
// should be performed. This is an alternative to using the signals, it has lower overhead and is thus less expensive,
|
||
// but also less flexible.
|
||
//
|
||
// If callbacks are installed, no signals will be emitted for performance reasons.
|
||
//
|
||
// Before 1.16.3 it was not possible to change the callbacks in a thread-safe way.
|
||
func (a *Source) SetCallbacks(cbs *SourceCallbacks) {
|
||
ptr := gopointer.Save(cbs)
|
||
appSrcCallbacks := &C.GstAppSrcCallbacks{
|
||
need_data: (*[0]byte)(unsafe.Pointer(C.cgoNeedDataCb)),
|
||
enough_data: (*[0]byte)(unsafe.Pointer(C.cgoEnoughDataCb)),
|
||
seek_data: (*[0]byte)(unsafe.Pointer(C.cgoSeekDataCb)),
|
||
}
|
||
C.gst_app_src_set_callbacks(
|
||
a.Instance(),
|
||
appSrcCallbacks,
|
||
(C.gpointer)(unsafe.Pointer(ptr)),
|
||
C.GDestroyNotify(C.cgoSrcGDestroyNotifyFunc),
|
||
)
|
||
}
|
||
|
||
// SetCaps sets the capabilities on the appsrc element. This function takes a copy of the caps structure. After calling this method,
|
||
// the source will only produce caps that match caps. caps must be fixed and the caps on the buffers must match the caps or left NULL.
|
||
func (a *Source) SetCaps(caps *gst.Caps) {
|
||
C.gst_app_src_set_caps(a.Instance(), (*C.GstCaps)(unsafe.Pointer(caps.Instance())))
|
||
}
|
||
|
||
// SetDuration sets the duration of the source stream. You should call
|
||
// this if the value is known.
|
||
func (a *Source) SetDuration(dur gst.ClockTime) {
|
||
C.gst_app_src_set_duration((*C.GstAppSrc)(a.Instance()), C.GstClockTime(dur))
|
||
}
|
||
|
||
// SetEmitSignals makes appsrc emit the "new-preroll" and "new-buffer" signals. This option is by default disabled because signal emission
|
||
// is expensive and unneeded when the application prefers to operate in pull mode.
|
||
func (a *Source) SetEmitSignals(emit bool) {
|
||
C.gst_app_src_set_emit_signals(a.Instance(), gboolean(emit))
|
||
}
|
||
|
||
// SetLatency configures the min and max latency in src. If min is set to -1, the default latency calculations for pseudo-live sources
|
||
// will be used.
|
||
func (a *Source) SetLatency(min, max uint64) {
|
||
C.gst_app_src_set_latency(a.Instance(), C.guint64(min), C.guint64(max))
|
||
}
|
||
|
||
// SetMaxBytes sets the maximum amount of bytes that can be queued in appsrc. After the maximum amount of bytes are queued, appsrc will
|
||
// emit the "enough-data" signal.
|
||
func (a *Source) SetMaxBytes(max uint64) {
|
||
C.gst_app_src_set_max_bytes(a.Instance(), C.guint64(max))
|
||
}
|
||
|
||
// SetSize sets the size of the source stream in bytes. You should call this for
|
||
// streams of fixed length.
|
||
func (a *Source) SetSize(size int64) {
|
||
C.gst_app_src_set_size((*C.GstAppSrc)(a.Instance()), (C.gint64)(size))
|
||
}
|
||
|
||
// SetStreamType sets the stream type on appsrc. For seekable streams, the "seek" signal must be connected to.
|
||
func (a *Source) SetStreamType(streamType StreamType) {
|
||
C.gst_app_src_set_stream_type(a.Instance(), C.GstAppStreamType(streamType))
|
||
}
|