move gstreamer-app bindings to separate package to not require when using main package

This commit is contained in:
tinyzimmer
2020-09-27 13:39:02 +03:00
parent af5324a2b5
commit a94f6258a5
42 changed files with 304 additions and 268 deletions

View File

@@ -23,9 +23,9 @@ For building applications with this library you need the following:
- `gcc` and `pkg-config`
- `libgstreamer-1.0-dev`: This package name may be different depending on your OS. You need the `gst.h` header files.
- In some distributions (such as alpine linux) this is in the `gstreamer-dev` package.
- To use the `app` or `gstauto/app` packages you will need additional dependencies:
- `libgstreamer-app-1.0-dev`: This package name may also be different depending on your os. You need the `gstappsink.h` and `gstappsrc.h`
- In some distributions (such as alpine linux) this is in the `gst-plugins-base-dev` package.
- I will likely turn this into an optional dependency.
- You may need platform specific headers also. For example, in alpine linux, you will most likely also need the `musl-dev` package.
For running applications with this library you'll need to have `libgstreamer-1.0` installed. Again, this package may be different depending on your OS.

View File

@@ -13,7 +13,7 @@ import (
"github.com/spf13/cobra"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/gstauto"
"github.com/tinyzimmer/go-gst/gst/gstauto/app"
)
var framesPerSecond int
@@ -74,7 +74,7 @@ func gifEncode(cmd *cobra.Command, args []string) error {
logInfo("gif", "Converting video to image frames")
gstPipeline, err := gstauto.NewPipelineReaderAppFromString(launchStr)
gstPipeline, err := app.NewPipelineReaderAppFromString(launchStr)
if err != nil {
return err
}

10
gst/app/doc.go Normal file
View File

@@ -0,0 +1,10 @@
/*
Package app contains bindings for the gstreamer-app C API. If you are trying
to build simple pipelines quickly (and optiionally readers/writers) see
the gstauto/app package.
The location of this library may be different depending on your OS. It is usually
either with the gst-plugins-base development headers or a separate package called
gstreamer-app.
*/
package app

14
gst/app/gst.go.c Normal file
View File

@@ -0,0 +1,14 @@
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
GstAppSink *
toGstAppSink(void *p)
{
return (GST_APP_SINK(p));
}
GstAppSrc *
toGstAppSrc(void *p)
{
return (GST_APP_SRC(p));
}

5
gst/app/gst.go.h Normal file
View File

@@ -0,0 +1,5 @@
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
GstAppSink * toGstAppSink (void *p);
GstAppSrc * toGstAppSrc (void *p);

View File

@@ -1,15 +1,20 @@
package gst
package app
// #include "gst.go.h"
import "C"
import "errors"
import (
"errors"
"unsafe"
// AppSink wraps an Element object with additional methods for pulling samples.
type AppSink struct{ *Element }
"github.com/tinyzimmer/go-gst/gst"
)
// Sink wraps an Element made with the appsink plugin with additional methods for pulling samples.
type Sink struct{ *gst.Element }
// NewAppSink returns a new appsink element. Unref after usage.
func NewAppSink() (*AppSink, error) {
elem, err := NewElement("appsink")
func NewAppSink() (*Sink, error) {
elem, err := gst.NewElement("appsink")
if err != nil {
return nil, err
}
@@ -17,19 +22,19 @@ func NewAppSink() (*AppSink, error) {
}
// Instance returns the native GstAppSink instance.
func (a *AppSink) Instance() *C.GstAppSink { return C.toGstAppSink(a.unsafe()) }
func (a *Sink) Instance() *C.GstAppSink { return C.toGstAppSink(a.Unsafe()) }
// ErrEOS represents that the stream has ended.
var ErrEOS = errors.New("Pipeline has reached end-of-stream")
// IsEOS returns true if this AppSink has reached the end-of-stream.
func (a *AppSink) IsEOS() bool {
func (a *Sink) IsEOS() bool {
return gobool(C.gst_app_sink_is_eos((*C.GstAppSink)(a.Instance())))
}
// BlockPullSample will block until a sample becomes available or the stream
// is ended.
func (a *AppSink) BlockPullSample() (*Sample, error) {
func (a *Sink) BlockPullSample() (*gst.Sample, error) {
for {
if a.IsEOS() {
return nil, ErrEOS
@@ -39,12 +44,12 @@ func (a *AppSink) BlockPullSample() (*Sample, error) {
if sample == nil {
continue
}
return wrapSample(sample), nil
return gst.FromGstSampleUnsafe(unsafe.Pointer(sample)), nil
}
}
// PullSample will try to pull a sample or return nil if none is available.
func (a *AppSink) PullSample() (*Sample, error) {
func (a *Sink) PullSample() (*gst.Sample, error) {
if a.IsEOS() {
return nil, ErrEOS
}
@@ -53,7 +58,7 @@ func (a *AppSink) PullSample() (*Sample, error) {
C.GST_SECOND,
)
if sample != nil {
return wrapSample(sample), nil
return gst.FromGstSampleUnsafe(unsafe.Pointer(sample)), nil
}
return nil, nil
}

View File

@@ -1,15 +1,20 @@
package gst
package app
// #include "gst.go.h"
import "C"
import "time"
import (
"time"
"unsafe"
// AppSrc wraps an Element object with additional methods for pushing samples.
type AppSrc struct{ *Element }
"github.com/tinyzimmer/go-gst/gst"
)
// Source wraps an Element made with the appsrc plugin with additional methods for pushing samples.
type Source struct{ *gst.Element }
// NewAppSrc returns a new AppSrc element.
func NewAppSrc() (*AppSrc, error) {
elem, err := NewElement("appsrc")
func NewAppSrc() (*Source, error) {
elem, err := gst.NewElement("appsrc")
if err != nil {
return nil, err
}
@@ -17,33 +22,36 @@ func NewAppSrc() (*AppSrc, error) {
}
// Instance returns the native GstAppSink instance.
func (a *AppSrc) Instance() *C.GstAppSrc { return C.toGstAppSrc(a.unsafe()) }
func (a *Source) Instance() *C.GstAppSrc { return C.toGstAppSrc(a.Unsafe()) }
// SetSize sets the size of the source stream in bytes. You should call this for
// streams of fixed length.
func (a *AppSrc) SetSize(size int64) {
func (a *Source) SetSize(size int64) {
C.gst_app_src_set_size((*C.GstAppSrc)(a.Instance()), (C.gint64)(size))
}
// SetDuration sets the duration of the source stream. You should call
// this if the value is known.
func (a *AppSrc) SetDuration(dur time.Duration) {
func (a *Source) SetDuration(dur time.Duration) {
C.gst_app_src_set_duration((*C.GstAppSrc)(a.Instance()), (C.ulong)(dur.Nanoseconds()))
}
// EndStream signals to the app source that the stream has ended after the last queued
// buffer.
func (a *AppSrc) EndStream() FlowReturn {
func (a *Source) EndStream() gst.FlowReturn {
ret := C.gst_app_src_end_of_stream((*C.GstAppSrc)(a.Instance()))
return FlowReturn(ret)
return gst.FlowReturn(ret)
}
// SetLive sets whether or not this is a live stream.
func (a *AppSrc) SetLive(b bool) error { return a.Set("is-live", b) }
func (a *Source) SetLive(b bool) error { return a.Set("is-live", b) }
// PushBuffer pushes a buffer to the appsrc. Currently by default this will block
// until the source is ready to accept the buffer.
func (a *AppSrc) PushBuffer(buf *Buffer) FlowReturn {
ret := C.gst_app_src_push_buffer((*C.GstAppSrc)(a.Instance()), (*C.GstBuffer)(buf.Instance()))
return FlowReturn(ret)
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.Instance())),
)
return gst.FlowReturn(ret)
}

7
gst/app/pkg_config.go Normal file
View File

@@ -0,0 +1,7 @@
package app
/*
#cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0
#cgo CFLAGS: -Wno-deprecated-declarations -g -Wall
*/
import "C"

22
gst/app/wrappers.go Normal file
View File

@@ -0,0 +1,22 @@
package app
// #include <gst/gst.h>
import "C"
import "github.com/tinyzimmer/go-gst/gst"
func wrapAppSink(elem *gst.Element) *Sink { return &Sink{elem} }
func wrapAppSrc(elem *gst.Element) *Source { return &Source{elem} }
// gobool provides an easy type conversion between C.gboolean and a go bool.
func gobool(b C.gboolean) bool {
return b != 0
}
// gboolean converts a go bool to a C.gboolean.
func gboolean(b bool) C.gboolean {
if b {
return C.gboolean(1)
}
return C.gboolean(0)
}

View File

@@ -1,45 +1,11 @@
package gst
/*
#cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0
#cgo CFLAGS: -Wno-deprecated-declarations -g -Wall
#include <gst/gst.h>
*/
// #include <gst/gst.h>
import "C"
import (
"errors"
"unsafe"
"github.com/gotk3/gotk3/glib"
)
// Init is a wrapper around gst_init() and must be called before any
// other gstreamer calls and is used to initialize everything necessary.
// In addition to setting up gstreamer for usage, a pointer to a slice of
// strings may be passed in to parse standard gst command line arguments.
// args will be modified to remove any flags that were handled.
// Alternatively, nil may be passed in to not perform any command line
// parsing.
func Init(args *[]string) {
if args != nil {
argc := C.int(len(*args))
argv := make([]*C.char, argc)
for i, arg := range *args {
argv[i] = C.CString(arg)
}
C.gst_init((*C.int)(unsafe.Pointer(&argc)),
(***C.char)(unsafe.Pointer(&argv)))
unhandled := make([]string, argc)
for i := 0; i < int(argc); i++ {
unhandled[i] = C.GoString(argv[i])
C.free(unsafe.Pointer(argv[i]))
}
*args = unhandled
} else {
C.gst_init(nil, nil)
}
}
// gobool provides an easy type conversion between C.gboolean and a go bool.
func gobool(b C.gboolean) bool {
return b != 0
@@ -53,28 +19,7 @@ func gboolean(b bool) C.gboolean {
return C.gboolean(0)
}
func iteratorToElementSlice(iterator *C.GstIterator) ([]*Element, error) {
elems := make([]*Element, 0)
gval := new(C.GValue)
for {
switch C.gst_iterator_next((*C.GstIterator)(iterator), (*C.GValue)(unsafe.Pointer(gval))) {
case C.GST_ITERATOR_DONE:
C.gst_iterator_free((*C.GstIterator)(iterator))
return elems, nil
case C.GST_ITERATOR_RESYNC:
C.gst_iterator_resync((*C.GstIterator)(iterator))
case C.GST_ITERATOR_OK:
cElemVoid := C.g_value_get_object((*C.GValue)(gval))
cElem := (*C.GstElement)(cElemVoid)
elems = append(elems, wrapElement(glib.Take(unsafe.Pointer(cElem))))
C.g_value_reset((*C.GValue)(gval))
default:
return nil, errors.New("Element iterator failed")
}
}
}
// goStrings returns a string slice for an array of size argc starting at the address argv.
func goStrings(argc C.int, argv **C.gchar) []string {
length := int(argc)
tmpslice := (*[1 << 30]*C.gchar)(unsafe.Pointer(argv))[:length:length]
@@ -85,6 +30,8 @@ func goStrings(argc C.int, argv **C.gchar) []string {
return gostrings
}
// newQuarkFromString creates a new GQuark (or returns an existing one) for the given
// string
func newQuarkFromString(str string) C.uint {
cstr := C.CString(str)
defer C.free(unsafe.Pointer(cstr))

View File

@@ -1,6 +1,4 @@
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
#include "gst.go.h"
/*
@@ -183,18 +181,6 @@ toGstElement(void *p)
return (GST_ELEMENT(p));
}
GstAppSink *
toGstAppSink(void *p)
{
return (GST_APP_SINK(p));
}
GstAppSrc *
toGstAppSrc(void *p)
{
return (GST_APP_SRC(p));
}
GstBin *
toGstBin(void *p)
{
@@ -272,3 +258,9 @@ toGstBufferPool(void *p)
{
return (GST_BUFFER_POOL(p));
}
GstSample *
toGstSample(void *p)
{
return (GST_SAMPLE(p));
}

View File

@@ -1,6 +1,4 @@
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
extern gboolean structForEachCb (GQuark field_id, GValue * value, gpointer user_data);
@@ -48,8 +46,6 @@ GstPluginFeature * toGstPluginFeature (void *p);
GstObject * toGstObject (void *p);
GstElementFactory * toGstElementFactory (void *p);
GstElement * toGstElement (void *p);
GstAppSink * toGstAppSink (void *p);
GstAppSrc * toGstAppSrc (void *p);
GstBin * toGstBin (void *p);
GstBus * toGstBus (void *p);
GstMessage * toGstMessage (void *p);
@@ -63,3 +59,4 @@ GstCaps * toGstCaps (void *p);
GstCapsFeatures * toGstCapsFeatures (void *p);
GstBuffer * toGstBuffer (void *p);
GstBufferPool * toGstBufferPool (void *p);
GstSample * toGstSample (void *p);

View File

@@ -3,6 +3,7 @@ package gst
// #include "gst.go.h"
import "C"
import (
"errors"
"fmt"
"unsafe"
@@ -13,7 +14,7 @@ import (
type Bin struct{ *Element }
// Instance returns the underlying GstBin instance.
func (b *Bin) Instance() *C.GstBin { return C.toGstBin(b.unsafe()) }
func (b *Bin) Instance() *C.GstBin { return C.toGstBin(b.Unsafe()) }
// GetElementByName returns the element with the given name. Unref after usage.
func (b *Bin) GetElementByName(name string) (*Element, error) {
@@ -47,7 +48,7 @@ func (b *Bin) GetSinkElements() ([]*Element, error) {
// Add wraps `gst_bin_add`.
func (b *Bin) Add(elem *Element) error {
if ok := C.gst_bin_add((*C.GstBin)(b.Instance()), (*C.GstElement)(elem.Instance())); !gobool(ok) {
if ok := C.gst_bin_add((*C.GstBin)(b.Instance()), (*C.GstElement)(elem.Instance())); gobool(ok) {
return fmt.Errorf("Failed to add element to pipeline: %s", elem.Name())
}
return nil
@@ -63,3 +64,25 @@ func (b *Bin) AddMany(elems ...*Element) error {
}
return nil
}
func iteratorToElementSlice(iterator *C.GstIterator) ([]*Element, error) {
elems := make([]*Element, 0)
gval := new(C.GValue)
for {
switch C.gst_iterator_next((*C.GstIterator)(iterator), (*C.GValue)(unsafe.Pointer(gval))) {
case C.GST_ITERATOR_DONE:
C.gst_iterator_free((*C.GstIterator)(iterator))
return elems, nil
case C.GST_ITERATOR_RESYNC:
C.gst_iterator_resync((*C.GstIterator)(iterator))
case C.GST_ITERATOR_OK:
cElemVoid := C.g_value_get_object((*C.GValue)(gval))
cElem := (*C.GstElement)(cElemVoid)
elems = append(elems, wrapElement(glib.Take(unsafe.Pointer(cElem))))
C.g_value_reset((*C.GValue)(gval))
default:
return nil, errors.New("Element iterator failed")
}
}
}

View File

@@ -18,7 +18,7 @@ type Bus struct {
}
// Instance returns the underlying GstBus instance.
func (b *Bus) Instance() *C.GstBus { return C.toGstBus(b.unsafe()) }
func (b *Bus) Instance() *C.GstBus { return C.toGstBus(b.Unsafe()) }
func (b *Bus) deliverMessages() {
for {

View File

@@ -8,7 +8,7 @@ import "time"
type Clock struct{ *Object }
// Instance returns the underlying GstClock instance.
func (c *Clock) Instance() *C.GstClock { return C.toGstClock(c.unsafe()) }
func (c *Clock) Instance() *C.GstClock { return C.toGstClock(c.Unsafe()) }
// IsSynced returns true if the clock is synced.
func (c *Clock) IsSynced() bool { return gobool(C.gst_clock_is_synced(c.Instance())) }

View File

@@ -29,7 +29,7 @@ func ElementLinkMany(elems ...*Element) error {
}
// Instance returns the underlying GstElement instance.
func (e *Element) Instance() *C.GstElement { return C.toGstElement(e.unsafe()) }
func (e *Element) Instance() *C.GstElement { return C.toGstElement(e.Unsafe()) }
// Link wraps gst_element_link and links this element to the given one.
func (e *Element) Link(elem *Element) error {
@@ -137,7 +137,7 @@ func (e *Element) GetPadTemplates() []*PadTemplate {
// Has returns true if this element has the given flags.
func (e *Element) Has(flags ElementFlags) bool {
return gobool(C.gstObjectFlagIsSet(C.toGstObject(e.unsafe()), C.GstElementFlags(flags)))
return gobool(C.gstObjectFlagIsSet(C.toGstObject(e.Unsafe()), C.GstElementFlags(flags)))
}
// IsURIHandler returns true if this element can handle URIs.
@@ -145,7 +145,7 @@ func (e *Element) IsURIHandler() bool {
return gobool(C.gstElementIsURIHandler(e.Instance()))
}
func (e *Element) uriHandler() *C.GstURIHandler { return C.toGstURIHandler(e.unsafe()) }
func (e *Element) uriHandler() *C.GstURIHandler { return C.toGstURIHandler(e.Unsafe()) }
// GetURIType returns the type of URI this element can handle.
func (e *Element) GetURIType() URIType {

View File

@@ -51,7 +51,7 @@ func Find(name string) *ElementFactory {
}
// Instance returns the C GstFactory instance
func (e *ElementFactory) Instance() *C.GstElementFactory { return C.toGstElementFactory(e.unsafe()) }
func (e *ElementFactory) Instance() *C.GstElementFactory { return C.toGstElementFactory(e.Unsafe()) }
// CanSinkAllCaps checks if the factory can sink all possible capabilities.
func (e *ElementFactory) CanSinkAllCaps(caps *C.GstCaps) bool {

View File

@@ -14,12 +14,12 @@ type Message struct {
msg *C.GstMessage
}
// Native returns the underlying GstMessage object.
func (m *Message) Native() *C.GstMessage { return C.toGstMessage(unsafe.Pointer(m.msg)) }
// Instance returns the underlying GstMessage object.
func (m *Message) Instance() *C.GstMessage { return C.toGstMessage(unsafe.Pointer(m.msg)) }
// Type returns the MessageType of the message.
func (m *Message) Type() MessageType {
return MessageType(m.Native()._type)
return MessageType(m.Instance()._type)
}
// TypeName returns a Go string of the GstMessageType name.
@@ -34,11 +34,11 @@ func (m *Message) GetStructure() *Structure {
switch m.Type() {
case MessageError:
C.gst_message_parse_error_details((*C.GstMessage)(m.Native()), (**C.GstStructure)(unsafe.Pointer(&st)))
C.gst_message_parse_error_details((*C.GstMessage)(m.Instance()), (**C.GstStructure)(unsafe.Pointer(&st)))
case MessageInfo:
C.gst_message_parse_info_details((*C.GstMessage)(m.Native()), (**C.GstStructure)(unsafe.Pointer(&st)))
C.gst_message_parse_info_details((*C.GstMessage)(m.Instance()), (**C.GstStructure)(unsafe.Pointer(&st)))
case MessageWarning:
C.gst_message_parse_warning_details((*C.GstMessage)(m.Native()), (**C.GstStructure)(unsafe.Pointer(&st)))
C.gst_message_parse_warning_details((*C.GstMessage)(m.Instance()), (**C.GstStructure)(unsafe.Pointer(&st)))
}
// if no structure was returned, immediately return nil
@@ -59,11 +59,11 @@ func (m *Message) parseToError() *GoGError {
switch m.Type() {
case MessageError:
C.gst_message_parse_error((*C.GstMessage)(m.Native()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
C.gst_message_parse_error((*C.GstMessage)(m.Instance()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
case MessageInfo:
C.gst_message_parse_info((*C.GstMessage)(m.Native()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
C.gst_message_parse_info((*C.GstMessage)(m.Instance()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
case MessageWarning:
C.gst_message_parse_warning((*C.GstMessage)(m.Native()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
C.gst_message_parse_warning((*C.GstMessage)(m.Instance()), (**C.GError)(unsafe.Pointer(&gerr)), (**C.gchar)(unsafe.Pointer(&debugInfo)))
}
// if error was nil return immediately
@@ -104,26 +104,26 @@ func (m *Message) ParseError() *GoGError {
// if the GstMessageType is `GST_MESSAGE_STATE_CHANGED`.
func (m *Message) ParseStateChanged() (oldState, newState State) {
var gOldState, gNewState C.GstState
C.gst_message_parse_state_changed((*C.GstMessage)(m.Native()), (*C.GstState)(unsafe.Pointer(&gOldState)), (*C.GstState)(unsafe.Pointer(&gNewState)), nil)
C.gst_message_parse_state_changed((*C.GstMessage)(m.Instance()), (*C.GstState)(unsafe.Pointer(&gOldState)), (*C.GstState)(unsafe.Pointer(&gNewState)), nil)
oldState = State(gOldState)
newState = State(gNewState)
return
}
// Unref will call `gst_message_unref` on the underlying GstMessage, freeing it from memory.
func (m *Message) Unref() { C.gst_message_unref((*C.GstMessage)(m.Native())) }
func (m *Message) Unref() { C.gst_message_unref((*C.GstMessage)(m.Instance())) }
// Ref will increase the ref count on this message. This increases the total amount of times
// Unref needs to be called before the object is freed from memory. It returns the underlying
// message object for convenience.
func (m *Message) Ref() *Message {
C.gst_message_ref((*C.GstMessage)(m.Native()))
C.gst_message_ref((*C.GstMessage)(m.Instance()))
return m
}
// Copy will copy this object into a new Message that can be Unrefed separately.
func (m *Message) Copy() *Message {
newNative := C.gst_message_copy((*C.GstMessage)(m.Native()))
newNative := C.gst_message_copy((*C.GstMessage)(m.Instance()))
return wrapMessage(newNative)
}

View File

@@ -13,14 +13,15 @@ import (
// and we do not descend into the glib library.
type Object struct{ *glib.InitiallyUnowned }
// native returns the pointer to the underlying object.
func (o *Object) unsafe() unsafe.Pointer { return unsafe.Pointer(o.InitiallyUnowned.Native()) }
// Unsafe returns the unsafe pointer to the underlying object. This method is primarily
// for internal usage and is exposed for visibility in other packages.
func (o *Object) Unsafe() unsafe.Pointer { return unsafe.Pointer(o.InitiallyUnowned.Native()) }
// Instance returns the native C GstObject.
func (o *Object) Instance() *C.GstObject { return C.toGstObject(o.unsafe()) }
func (o *Object) Instance() *C.GstObject { return C.toGstObject(o.Unsafe()) }
// Class returns the GObjectClass of this instance.
func (o *Object) Class() *C.GObjectClass { return C.getGObjectClass(o.unsafe()) }
func (o *Object) Class() *C.GObjectClass { return C.getGObjectClass(o.Unsafe()) }
// Name returns the name of this object.
func (o *Object) Name() string {
@@ -61,7 +62,7 @@ func (o *Object) ListProperties() []*ParameterSpec {
var gval C.GValue
flags := ParameterFlags(prop.flags)
if flags.Has(ParameterReadable) {
C.g_object_get_property((*C.GObject)(o.unsafe()), prop.name, &gval)
C.g_object_get_property((*C.GObject)(o.Unsafe()), prop.name, &gval)
} else {
C.g_param_value_set_default((*C.GParamSpec)(prop), &gval)
}

View File

@@ -12,7 +12,7 @@ import (
type Pad struct{ *Object }
// Instance returns the underlying C GstPad.
func (p *Pad) Instance() *C.GstPad { return C.toGstPad(p.unsafe()) }
func (p *Pad) Instance() *C.GstPad { return C.toGstPad(p.Unsafe()) }
// Direction returns the direction of this pad.
func (p *Pad) Direction() PadDirection {
@@ -37,7 +37,7 @@ func (p *Pad) CurrentCaps() *Caps {
type PadTemplate struct{ *Object }
// Instance returns the underlying C GstPadTemplate.
func (p *PadTemplate) Instance() *C.GstPadTemplate { return C.toGstPadTemplate(p.unsafe()) }
func (p *PadTemplate) Instance() *C.GstPadTemplate { return C.toGstPadTemplate(p.Unsafe()) }
// Name returns the name of the pad template.
func (p *PadTemplate) Name() string { return C.GoString(p.Instance().name_template) }

View File

@@ -51,7 +51,7 @@ func NewPipelineFromString(launchv string) (*Pipeline, error) {
}
// Instance returns the native GstPipeline instance.
func (p *Pipeline) Instance() *C.GstPipeline { return C.toGstPipeline(p.unsafe()) }
func (p *Pipeline) Instance() *C.GstPipeline { return C.toGstPipeline(p.Unsafe()) }
// GetPipelineBus returns the message bus for this pipeline.
func (p *Pipeline) GetPipelineBus() *Bus {

View File

@@ -7,7 +7,7 @@ import "C"
type Plugin struct{ *Object }
// Instance returns the underlying GstPlugin instance.
func (p *Plugin) Instance() *C.GstPlugin { return C.toGstPlugin(p.unsafe()) }
func (p *Plugin) Instance() *C.GstPlugin { return C.toGstPlugin(p.Unsafe()) }
// Description returns the description for this plugin.
func (p *Plugin) Description() string {

View File

@@ -12,7 +12,7 @@ import (
type PluginFeature struct{ *Object }
// Instance returns the underlying GstPluginFeature instance
func (p *PluginFeature) Instance() *C.GstPluginFeature { return C.toGstPluginFeature(p.unsafe()) }
func (p *PluginFeature) Instance() *C.GstPluginFeature { return C.toGstPluginFeature(p.Unsafe()) }
// GetPlugin returns the plugin that provides this feature or nil. Unref after usage.
func (p *PluginFeature) GetPlugin() *Plugin {

View File

@@ -19,7 +19,7 @@ func GetRegistry() *Registry {
}
// Instance returns the underlying GstRegistry instance.
func (r *Registry) Instance() *C.GstRegistry { return C.toGstRegistry(r.unsafe()) }
func (r *Registry) Instance() *C.GstRegistry { return C.toGstRegistry(r.Unsafe()) }
// FindPlugin retrieves the plugin by the given name. Unref after usage.
func (r *Registry) FindPlugin(name string) (*Plugin, error) {

View File

@@ -2,14 +2,19 @@ package gst
// #include "gst.go.h"
import "C"
import "unsafe"
// Sample is a go wrapper around a GstSample object.
type Sample struct {
sample *C.GstSample
}
// FromGstSampleUnsafe wraps the pointer to the given C GstSample with the go type.
// This is meant for internal usage and is exported for visibility to other packages.
func FromGstSampleUnsafe(sample unsafe.Pointer) *Sample { return wrapSample(C.toGstSample(sample)) }
// Instance returns the underlying *GstSample instance.
func (s *Sample) Instance() *C.GstSample { return s.sample }
func (s *Sample) Instance() *C.GstSample { return C.toGstSample(unsafe.Pointer(s.sample)) }
// Unref calls gst_sample_unref on the sample.
func (s *Sample) Unref() { C.gst_sample_unref((*C.GstSample)(s.Instance())) }

View File

@@ -113,9 +113,6 @@ func wrapGhostPad(obj *glib.Object) *GhostPad { return &GhostPad{wrapPad(o
func wrapPlugin(obj *glib.Object) *Plugin { return &Plugin{wrapObject(obj)} }
func wrapRegistry(obj *glib.Object) *Registry { return &Registry{wrapObject(obj)} }
func wrapAppSink(elem *Element) *AppSink { return &AppSink{elem} }
func wrapAppSrc(elem *Element) *AppSrc { return &AppSrc{elem} }
func wrapSample(sample *C.GstSample) *Sample { return &Sample{sample: sample} }
func wrapBuffer(buf *C.GstBuffer) *Buffer { return &Buffer{ptr: buf} }

7
gst/gstauto/app/doc.go Normal file
View File

@@ -0,0 +1,7 @@
// Package app provides interfaces from the gstauto package that
// use the gstreamer-app library for interacting with either end
// of the pipeline.
//
// Using this package will require additional dependencies at build and runtime.
// See the README in the main repo for details.
package app

View File

@@ -1,4 +1,4 @@
package gstauto
package app
import (
"errors"
@@ -6,15 +6,17 @@ import (
"strings"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
"github.com/tinyzimmer/go-gst/gst/gstauto"
)
// PipelineReaderApp implements a ReadPipeliner that configures gstreamer
// with an appsink. The appsink allows for more granular control over the data
// at the end of the pipeline.
type PipelineReaderApp struct {
*PipelineReader
*gstauto.PipelineReader
appSink *gst.AppSink
appSink *app.Sink
}
// NewPipelineReaderAppFromString returns a new PipelineReaderApp populated from
@@ -22,32 +24,25 @@ type PipelineReaderApp struct {
// available via the GetAppSink method.
func NewPipelineReaderAppFromString(launchStr string) (*PipelineReaderApp, error) {
fmt.Println(addAppSinkToStr(launchStr))
pipelineReader, err := NewPipelineReaderFromString(addAppSinkToStr(launchStr))
pipelineReader, err := gstauto.NewPipelineReaderFromString(addAppSinkToStr(launchStr))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineReader.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
}
}()
appPipeline := &PipelineReaderApp{PipelineReader: pipelineReader}
// Retrieve the sinks in the pipeline, most of the time there is just one
var sinks []*gst.Element
sinks, err = pipelineReader.Pipeline().GetSinkElements()
if err != nil {
runOrPrintErr(pipelineReader.Pipeline().Destroy)
return nil, err
}
// Fetch the appsink and make a local reference to it
for _, sink := range sinks {
if strings.Contains(sink.Name(), "appsink") {
appPipeline.appSink = &gst.AppSink{Element: sink}
appPipeline.appSink = &app.Sink{Element: sink}
}
}
@@ -58,24 +53,22 @@ func NewPipelineReaderAppFromString(launchStr string) (*PipelineReaderApp, error
// NewPipelineReaderAppFromConfig returns a new PipelineReaderApp populated from
// the given launch config. An appsink is added to the end of the launch config and
// made available via the GetAppSink method.
func NewPipelineReaderAppFromConfig(cfg *PipelineConfig) (*PipelineReaderApp, error) {
func NewPipelineReaderAppFromConfig(cfg *gstauto.PipelineConfig) (*PipelineReaderApp, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineReader, err := NewPipelineReader("")
pipelineReader, err := gstauto.NewPipelineReader("")
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineReader.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReader.Pipeline().Destroy)
}
}()
cfg.Elements = append(cfg.Elements, &PipelineElement{Name: "appsink"})
cfg.Elements = append(cfg.Elements, &gstauto.PipelineElement{Name: "appsink"})
if err = cfg.Apply(pipelineReader.Pipeline()); err != nil {
return nil, err
@@ -93,7 +86,7 @@ func NewPipelineReaderAppFromConfig(cfg *PipelineConfig) (*PipelineReaderApp, er
// Fetch the appsink and make a local reference to it
for _, sink := range sinks {
if strings.Contains(sink.Name(), "appsink") {
appPipeline.appSink = &gst.AppSink{Element: sink}
appPipeline.appSink = &app.Sink{Element: sink}
}
}
@@ -108,4 +101,4 @@ func addAppSinkToStr(pstr string) string {
}
// GetAppSink returns the app sink for this pipeline.
func (p *PipelineReaderApp) GetAppSink() *gst.AppSink { return p.appSink }
func (p *PipelineReaderApp) GetAppSink() *app.Sink { return p.appSink }

View File

@@ -1,11 +1,12 @@
package gstauto
package app
import (
"errors"
"fmt"
"strings"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
"github.com/tinyzimmer/go-gst/gst/gstauto"
)
// PipelineReadWriterApp implements a ReadPipeliner that configures gstreamer
@@ -13,10 +14,10 @@ import (
// at the end of the pipeline, and the appsrc allows for control over the data
// at the start.
type PipelineReadWriterApp struct {
*PipelineReadWriter
*gstauto.PipelineReadWriter
appSrc *gst.AppSrc
appSink *gst.AppSink
appSrc *app.Source
appSink *app.Sink
}
// NewPipelineReadWriterAppFromString returns a new PipelineReadWriterApp populated from
@@ -24,16 +25,14 @@ type PipelineReadWriterApp struct {
// available via the GetAppSink method, and an appsrc is added to the end and made
// available via the GetAppSource method.
func NewPipelineReadWriterAppFromString(launchStr string) (*PipelineReadWriterApp, error) {
pipelineReadWriter, err := NewPipelineReadWriterFromString(addAppSourceToStr(addAppSinkToStr(launchStr)))
pipelineReadWriter, err := gstauto.NewPipelineReadWriterFromString(addAppSourceToStr(addAppSinkToStr(launchStr)))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineReadWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
}
}()
@@ -49,7 +48,7 @@ func NewPipelineReadWriterAppFromString(launchStr string) (*PipelineReadWriterAp
// Fetch the appsrc and make a local reference to it
for _, src := range sources {
if strings.Contains(src.Name(), "appsrc") {
appPipeline.appSrc = &gst.AppSrc{Element: src}
appPipeline.appSrc = &app.Source{Element: src}
}
}
@@ -63,7 +62,7 @@ func NewPipelineReadWriterAppFromString(launchStr string) (*PipelineReadWriterAp
// Fetch the appsink and make a local reference to it
for _, sink := range sinks {
if strings.Contains(sink.Name(), "appsink") {
appPipeline.appSink = &gst.AppSink{Element: sink}
appPipeline.appSink = &app.Sink{Element: sink}
}
}
@@ -75,24 +74,22 @@ func NewPipelineReadWriterAppFromString(launchStr string) (*PipelineReadWriterAp
// the given launch config. An appsink is added to the end of the launch config and
// made available via the GetAppSink method, and an appsrc is added at the front and made
// available via the GetAppSource method.
func NewPipelineReadWriterAppFromConfig(cfg *PipelineConfig) (*PipelineReadWriterApp, error) {
func NewPipelineReadWriterAppFromConfig(cfg *gstauto.PipelineConfig) (*PipelineReadWriterApp, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineReadWriter, err := NewPipelineReadWriter("")
pipelineReadWriter, err := gstauto.NewPipelineReadWriter("")
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineReadWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
}
}()
cfg.Elements = append(cfg.Elements, &PipelineElement{Name: "appsink"})
cfg.Elements = append(cfg.Elements, &gstauto.PipelineElement{Name: "appsink"})
if err = cfg.Apply(pipelineReadWriter.Pipeline()); err != nil {
return nil, err
@@ -110,7 +107,7 @@ func NewPipelineReadWriterAppFromConfig(cfg *PipelineConfig) (*PipelineReadWrite
// Fetch the appsrc and make a local reference to it
for _, src := range sources {
if strings.Contains(src.Name(), "appsrc") {
appPipeline.appSrc = &gst.AppSrc{Element: src}
appPipeline.appSrc = &app.Source{Element: src}
}
}
@@ -124,7 +121,7 @@ func NewPipelineReadWriterAppFromConfig(cfg *PipelineConfig) (*PipelineReadWrite
// Fetch the appsink and make a local reference to it
for _, sink := range sinks {
if strings.Contains(sink.Name(), "appsink") {
appPipeline.appSink = &gst.AppSink{Element: sink}
appPipeline.appSink = &app.Sink{Element: sink}
}
}
@@ -132,7 +129,7 @@ func NewPipelineReadWriterAppFromConfig(cfg *PipelineConfig) (*PipelineReadWrite
}
// GetAppSink returns the app sink for this pipeline.
func (p *PipelineReadWriterApp) GetAppSink() *gst.AppSink { return p.appSink }
func (p *PipelineReadWriterApp) GetAppSink() *app.Sink { return p.appSink }
// GetAppSource returns the app src for this pipeline.
func (p *PipelineReadWriterApp) GetAppSource() *gst.AppSrc { return p.appSrc }
func (p *PipelineReadWriterApp) GetAppSource() *app.Source { return p.appSrc }

View File

@@ -1,4 +1,4 @@
package gstauto
package app
import (
"errors"
@@ -6,47 +6,42 @@ import (
"strings"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
"github.com/tinyzimmer/go-gst/gst/gstauto"
)
// PipelineWriterApp implements a WritePipeliner that configures gstreamer
// with an appsrc. The appsrc allows for more granular control over the data
// at the start of the pipeline.
type PipelineWriterApp struct {
*PipelineWriter
*gstauto.PipelineWriter
appSrc *gst.AppSrc
appSrc *app.Source
}
// NewPipelineWriterAppFromString returns a new PipelineWriterApp populated from
// the given launch string. An appsrc is added to the start of the launch string and made
// available via the GetAppSource method.
func NewPipelineWriterAppFromString(launchStr string) (*PipelineWriterApp, error) {
pipelineWriter, err := NewPipelineWriterFromString(addAppSourceToStr(launchStr))
pipelineWriter, err := gstauto.NewPipelineWriterFromString(addAppSourceToStr(launchStr))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
}
}()
appPipeline := &PipelineWriterApp{PipelineWriter: pipelineWriter}
// Retrieve the sources in the pipeline, most of the time there is just one
var sources []*gst.Element
sources, err = pipelineWriter.Pipeline().GetSourceElements()
if err != nil {
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
return nil, err
}
// Fetch the appsrc and make a local reference to it
for _, src := range sources {
if strings.Contains(src.Name(), "appsrc") {
appPipeline.appSrc = &gst.AppSrc{Element: src}
appPipeline.appSrc = &app.Source{Element: src}
}
}
@@ -57,24 +52,22 @@ func NewPipelineWriterAppFromString(launchStr string) (*PipelineWriterApp, error
// NewPipelineWriterAppFromConfig returns a new PipelineWriterApp populated from
// the given launch config. An appsrc is added to the start of the launch config and
// made available via the GetAppSource method.
func NewPipelineWriterAppFromConfig(cfg *PipelineConfig) (*PipelineWriterApp, error) {
func NewPipelineWriterAppFromConfig(cfg *gstauto.PipelineConfig) (*PipelineWriterApp, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineWriter, err := NewPipelineWriter("")
pipelineWriter, err := gstauto.NewPipelineWriter("")
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if destroyErr := pipelineWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
}
}()
cfg.pushPluginToTop(&PipelineElement{Name: "appsrc"})
cfg.PushPluginToTop(&gstauto.PipelineElement{Name: "appsrc"})
if err = cfg.Apply(pipelineWriter.Pipeline()); err != nil {
return nil, err
@@ -92,7 +85,7 @@ func NewPipelineWriterAppFromConfig(cfg *PipelineConfig) (*PipelineWriterApp, er
// Fetch the appsrc and make a local reference to it
for _, src := range sources {
if strings.Contains(src.Name(), "appsrc") {
appPipeline.appSrc = &gst.AppSrc{Element: src}
appPipeline.appSrc = &app.Source{Element: src}
}
}
@@ -107,4 +100,4 @@ func addAppSourceToStr(pstr string) string {
}
// GetAppSource returns the app src for this pipeline.
func (p *PipelineWriterApp) GetAppSource() *gst.AppSrc { return p.appSrc }
func (p *PipelineWriterApp) GetAppSource() *app.Source { return p.appSrc }

9
gst/gstauto/app/util.go Normal file
View File

@@ -0,0 +1,9 @@
package app
import "fmt"
func runOrPrintErr(f func() error) {
if err := f(); err != nil {
fmt.Println("[go-gst/gst/gstauto] Internal Error:", err.Error())
}
}

View File

@@ -2,7 +2,6 @@ package gstauto
import (
"errors"
"fmt"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -45,8 +44,8 @@ func (p *PipelineConfig) ElementNames() []string {
return names
}
// pushPluginToTop pushes a plugin to the top of the list.
func (p *PipelineConfig) pushPluginToTop(elem *PipelineElement) {
// PushPluginToTop pushes a plugin to the top of the list of elements.
func (p *PipelineConfig) PushPluginToTop(elem *PipelineElement) {
newSlc := []*PipelineElement{elem}
newSlc = append(newSlc, p.Elements...)
p.Elements = newSlc
@@ -124,16 +123,8 @@ func NewPipelineFromConfig(cfg *PipelineConfig) (*gst.Pipeline, error) {
return nil, err
}
// if any error happens while setting up the pipeline, immediately free it
defer func() {
if err != nil {
if destroyErr := pipeline.Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", err.Error())
}
}
}()
if err = cfg.Apply(pipeline); err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}

View File

@@ -1,8 +1,6 @@
package gstauto
import (
"fmt"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -25,9 +23,7 @@ func NewPipelineReader(name string) (*PipelineReader, error) {
}
rCloser, err := newReadCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReader{
@@ -46,9 +42,7 @@ func NewPipelineReaderFromString(launchStr string) (*PipelineReader, error) {
}
rCloser, err := newReadCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReader{

View File

@@ -1,8 +1,6 @@
package gstauto
import (
"fmt"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -25,9 +23,7 @@ func NewPipelineReadWriter(name string) (*PipelineReadWriter, error) {
}
rwCloser, err := newReadWriteCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReadWriter{
@@ -46,9 +42,7 @@ func NewPipelineReadWriterFromString(launchStr string) (*PipelineReadWriter, err
}
rwCloser, err := newReadWriteCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReadWriter{

View File

@@ -1,8 +1,6 @@
package gstauto
import (
"fmt"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -48,9 +46,7 @@ func NewPipelinerSimpleFromConfig(cfg *PipelineConfig) (*PipelinerSimple, error)
return nil, err
}
if err := cfg.Apply(pipeline); err != nil {
if destroyErr := pipeline.Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelinerSimple{pipeline: pipeline}, nil

View File

@@ -25,9 +25,7 @@ func NewPipelineReaderSimpleFromString(launchStr string) (*PipelineReaderSimple,
defer func() {
if err != nil {
if destroyErr := pipelineReader.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReader.Pipeline().Destroy)
}
}()
@@ -69,9 +67,7 @@ func NewPipelineReaderSimpleFromConfig(cfg *PipelineConfig) (*PipelineReaderSimp
},
})
if err := cfg.Apply(pipelineReader.Pipeline()); err != nil {
if destroyErr := pipelineReader.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReader.Pipeline().Destroy)
return nil, err
}
return &PipelineReaderSimple{pipelineReader}, nil

View File

@@ -2,7 +2,6 @@ package gstauto
import (
"errors"
"fmt"
"strings"
"github.com/tinyzimmer/go-gst/gst"
@@ -26,9 +25,7 @@ func NewPipelineReadWriterSimpleFromString(launchStr string) (*PipelineReadWrite
defer func() {
if err != nil {
if destroyErr := pipelineReadWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
}
}()
@@ -79,7 +76,7 @@ func NewPipelineReadWriterSimpleFromConfig(cfg *PipelineConfig) (*PipelineReadWr
if err != nil {
return nil, err
}
cfg.pushPluginToTop(&PipelineElement{
cfg.PushPluginToTop(&PipelineElement{
Name: "fdsrc",
Data: map[string]interface{}{
"fd": pipelineReadWriter.WriterFd(),
@@ -92,9 +89,7 @@ func NewPipelineReadWriterSimpleFromConfig(cfg *PipelineConfig) (*PipelineReadWr
},
})
if err := cfg.Apply(pipelineReadWriter.Pipeline()); err != nil {
if destroyErr := pipelineReadWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
return nil, err
}
return &PipelineReadWriterSimple{pipelineReadWriter}, nil

View File

@@ -25,9 +25,7 @@ func NewPipelineWriterSimpleFromString(launchStr string) (*PipelineWriterSimple,
defer func() {
if err != nil {
if destroyErr := pipelineWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
}
}()
@@ -62,16 +60,14 @@ func NewPipelineWriterSimpleFromConfig(cfg *PipelineConfig) (*PipelineWriterSimp
if err != nil {
return nil, err
}
cfg.pushPluginToTop(&PipelineElement{
cfg.PushPluginToTop(&PipelineElement{
Name: "fdsrc",
Data: map[string]interface{}{
"fd": pipelineWriter.WriterFd(),
},
})
if err := cfg.Apply(pipelineWriter.Pipeline()); err != nil {
if destroyErr := pipelineWriter.Pipeline().Destroy(); destroyErr != nil {
fmt.Println("[go-gst] Error while destroying failed pipeline instance:", destroyErr.Error())
}
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
return nil, err
}
return &PipelineWriterSimple{pipelineWriter}, nil

View File

@@ -1,8 +1,6 @@
package gstauto
import (
"fmt"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -25,9 +23,7 @@ func NewPipelineWriter(name string) (*PipelineWriter, error) {
}
wCloser, err := newWriteCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineWriter{
@@ -46,9 +42,7 @@ func NewPipelineWriterFromString(launchStr string) (*PipelineWriter, error) {
}
wCloser, err := newWriteCloser()
if err != nil {
if closeErr := pipeline.Destroy(); closeErr != nil {
fmt.Println("[gst-auto] Failed to destroy errored pipeline:", closeErr.Error())
}
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineWriter{

9
gst/gstauto/util.go Normal file
View File

@@ -0,0 +1,9 @@
package gstauto
import "fmt"
func runOrPrintErr(f func() error) {
if err := f(); err != nil {
fmt.Println("[go-gst/gst/gstauto] Internal Error:", err.Error())
}
}

32
gst/init.go Normal file
View File

@@ -0,0 +1,32 @@
package gst
// #include "gst.go.h"
import "C"
import "unsafe"
// Init is a wrapper around gst_init() and must be called before any
// other gstreamer calls and is used to initialize everything necessary.
// In addition to setting up gstreamer for usage, a pointer to a slice of
// strings may be passed in to parse standard gst command line arguments.
// args will be modified to remove any flags that were handled.
// Alternatively, nil may be passed in to not perform any command line
// parsing.
func Init(args *[]string) {
if args != nil {
argc := C.int(len(*args))
argv := make([]*C.char, argc)
for i, arg := range *args {
argv[i] = C.CString(arg)
}
C.gst_init((*C.int)(unsafe.Pointer(&argc)),
(***C.char)(unsafe.Pointer(&argv)))
unhandled := make([]string, argc)
for i := 0; i < int(argc); i++ {
unhandled[i] = C.GoString(argv[i])
C.free(unsafe.Pointer(argv[i]))
}
*args = unhandled
} else {
C.gst_init(nil, nil)
}
}

7
gst/pkg_config.go Normal file
View File

@@ -0,0 +1,7 @@
package gst
/*
#cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0
#cgo CFLAGS: -Wno-deprecated-declarations -g -Wall
*/
import "C"