From 25b79e2b5c1f47f2650eefa17bc8758eda7c0dc3 Mon Sep 17 00:00:00 2001 From: tinyzimmer <38474291+tinyzimmer@users.noreply.github.com> Date: Sun, 27 Sep 2020 09:48:11 +0300 Subject: [PATCH] add some more methods to the Pipeline object, clean up docs --- go.mod | 1 + go.sum | 2 ++ gst/gst_element.go | 29 +++++++++++++++-------------- gst/gst_pipeline.go | 44 ++++++++++++++++++++++++++++++-------------- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 964e113..17b47a9 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,6 @@ require ( github.com/gotk3/gotk3 v0.4.0 github.com/mattn/go-pointer v0.0.1 github.com/spf13/cobra v1.0.0 + github.com/tinyzimmer/go-gst-launch v0.0.10 // indirect golang.org/x/net v0.0.0-20190522155817-f3200d17e092 ) diff --git a/go.sum b/go.sum index 53d03f0..1a776a7 100644 --- a/go.sum +++ b/go.sum @@ -86,6 +86,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/tinyzimmer/go-gst-launch v0.0.10 h1:KyHnaqabbBtAyr7WADBeUrfLDH6H2tpqdVoNew1sSZc= +github.com/tinyzimmer/go-gst-launch v0.0.10/go.mod h1:OrGpiXW8hHT7r18jCku5Tc/RDArJYhOpQY85M5RFXTU= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= diff --git a/gst/gst_element.go b/gst/gst_element.go index d0bf89a..1405c3e 100644 --- a/gst/gst_element.go +++ b/gst/gst_element.go @@ -9,7 +9,6 @@ package gst import "C" import ( - "errors" "fmt" "unsafe" @@ -54,13 +53,24 @@ func (e *Element) LinkFiltered(elem *Element, caps *Caps) error { return nil } -// GetBus returns the GstBus for retrieving messages from this element. -func (e *Element) GetBus() (*Bus, error) { +// GetBus returns the GstBus for retrieving messages from this element. This function returns +// nil unless the element is a Pipeline. +func (e *Element) GetBus() *Bus { bus := C.gst_element_get_bus((*C.GstElement)(e.Instance())) if bus == nil { - return nil, errors.New("Could not retrieve bus from element") + return nil } - return wrapBus(glib.Take(unsafe.Pointer(bus))), nil + return wrapBus(glib.Take(unsafe.Pointer(bus))) +} + +// GetClock returns the Clock for this element. This is the clock as was last set with gst_element_set_clock. +// Elements in a pipeline will only have their clock set when the pipeline is in the PLAYING state. +func (e *Element) GetClock() *Clock { + cClock := C.gst_element_get_clock((*C.GstElement)(e.Instance())) + if cClock == nil { + return nil + } + return wrapClock(glib.Take(unsafe.Pointer(cClock))) } // GetState returns the current state of this element. @@ -130,15 +140,6 @@ func (e *Element) GetPadTemplates() []*PadTemplate { return out } -// GetClock returns the clock for this element or nil. Unref after usage. -func (e *Element) GetClock() *Clock { - clock := C.gst_element_get_clock((*C.GstElement)(e.Instance())) - if clock == nil { - return nil - } - return wrapClock(glib.Take(unsafe.Pointer(clock))) -} - // 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))) diff --git a/gst/gst_pipeline.go b/gst/gst_pipeline.go index b50385e..8885e62 100644 --- a/gst/gst_pipeline.go +++ b/gst/gst_pipeline.go @@ -20,13 +20,7 @@ import ( // Pipeline is a go implementation of a GstPipeline. Helper methods are provided for constructing // pipelines either using file descriptors or the Appsrc/Appsink APIs. The struct itself implements // a ReadWriteCloser. -type Pipeline struct { - *Bin - - // a local reference to the bus so duplicates aren't created - // when retrieved by the user - bus *Bus -} +type Pipeline struct{ *Bin } // NewPipeline allocates and returns a new empty pipeline. If name is empty, one // is generated by gstreamer. @@ -65,15 +59,37 @@ func (p *Pipeline) Instance() *C.GstPipeline { return C.toGstPipeline(p.unsafe() // GetBus returns the message bus for this pipeline. func (p *Pipeline) GetBus() *Bus { - if p.bus == nil { - cBus := C.gst_pipeline_get_bus((*C.GstPipeline)(p.Instance())) - p.bus = wrapBus(glib.Take(unsafe.Pointer(cBus))) - } - return p.bus + cBus := C.gst_pipeline_get_bus((*C.GstPipeline)(p.Instance())) + return wrapBus(glib.Take(unsafe.Pointer(cBus))) } -// Start will start the GstPipeline. It is asynchronous so it does not need to be -// called within a goroutine, however, it is still safe to do so. +// GetPipelineClock returns the global clock for this pipeline. +func (p *Pipeline) GetPipelineClock() *Clock { + cClock := C.gst_pipeline_get_pipeline_clock((*C.GstPipeline)(p.Instance())) + return wrapClock(glib.Take(unsafe.Pointer(cClock))) +} + +/* +SetAutoFlushBus can be used to disable automatically flushing the message bus +when a pipeline goes to StateNull. + +Usually, when a pipeline goes from READY to NULL state, it automatically flushes +all pending messages on the bus, which is done for refcounting purposes, to break +circular references. + +This means that applications that update state using (async) bus messages (e.g. do +certain things when a pipeline goes from PAUSED to READY) might not get to see +messages when the pipeline is shut down, because they might be flushed before they +can be dispatched in the main thread. This behaviour can be disabled using this function. + +It is important that all messages on the bus are handled when the automatic flushing +is disabled else memory leaks will be introduced. +*/ +func (p *Pipeline) SetAutoFlushBus(b bool) { + C.gst_pipeline_set_auto_flush_bus(p.Instance(), gboolean(b)) +} + +// Start is the equivalent to calling SetState(StatePlaying) on the underlying GstElement. func (p *Pipeline) Start() error { return p.SetState(StatePlaying) }