mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-16 13:00:58 +08:00
move gstreamer-app bindings to separate package to not require when using main package
This commit is contained in:
@@ -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.
|
||||
|
@@ -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
10
gst/app/doc.go
Normal 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
14
gst/app/gst.go.c
Normal 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
5
gst/app/gst.go.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <gst/app/gstappsink.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
|
||||
GstAppSink * toGstAppSink (void *p);
|
||||
GstAppSrc * toGstAppSrc (void *p);
|
@@ -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
|
||||
}
|
@@ -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
7
gst/app/pkg_config.go
Normal 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
22
gst/app/wrappers.go
Normal 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)
|
||||
}
|
@@ -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))
|
||||
|
20
gst/gst.go.c
20
gst/gst.go.c
@@ -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));
|
||||
}
|
||||
|
@@ -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);
|
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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())) }
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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)
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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) }
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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) {
|
||||
|
@@ -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())) }
|
||||
|
@@ -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
7
gst/gstauto/app/doc.go
Normal 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
|
@@ -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 }
|
@@ -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 }
|
@@ -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
9
gst/gstauto/app/util.go
Normal 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())
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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{
|
||||
|
@@ -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{
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
9
gst/gstauto/util.go
Normal 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
32
gst/init.go
Normal 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
7
gst/pkg_config.go
Normal 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"
|
Reference in New Issue
Block a user