mirror of
https://github.com/go-gst/go-gst.git
synced 2025-09-27 04:15:56 +08:00
change clockTime type, add more bindings
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/go-gst/go-gst/examples"
|
||||
"github.com/go-gst/go-gst/gst"
|
||||
@@ -116,7 +115,7 @@ func mainLoop(pipeline *gst.Pipeline) error {
|
||||
|
||||
// Loop over messsages from the pipeline
|
||||
for {
|
||||
msg := bus.TimedPop(time.Duration(-1))
|
||||
msg := bus.TimedPop(gst.ClockTimeNone)
|
||||
if msg == nil {
|
||||
break
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/go-gst/go-glib/glib"
|
||||
"github.com/go-gst/go-gst/examples"
|
||||
@@ -87,7 +86,7 @@ func padProbes(mainLoop *glib.MainLoop) error {
|
||||
|
||||
// Block on messages coming in from the bus instead of using the main loop
|
||||
for {
|
||||
msg := pipeline.GetPipelineBus().TimedPop(time.Duration(-1))
|
||||
msg := pipeline.GetPipelineBus().TimedPop(gst.ClockTimeNone)
|
||||
if msg == nil {
|
||||
break
|
||||
}
|
||||
|
@@ -23,7 +23,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-gst/go-gst/examples"
|
||||
"github.com/go-gst/go-gst/gst"
|
||||
@@ -65,7 +64,7 @@ func tagsetter() error {
|
||||
var cont bool
|
||||
var pipelineErr error
|
||||
for {
|
||||
msg := pipeline.GetPipelineBus().TimedPop(time.Duration(-1))
|
||||
msg := pipeline.GetPipelineBus().TimedPop(gst.ClockTimeNone)
|
||||
if msg == nil {
|
||||
break
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ func tagsetter(mainLoop *glib.MainLoop) error {
|
||||
// timed_pop on the bus with the desired timeout for when to stop waiting for new messages.
|
||||
// (-1 = Wait forever)
|
||||
for {
|
||||
msg := pipeline.GetPipelineBus().TimedPop(time.Duration(-1))
|
||||
msg := pipeline.GetPipelineBus().TimedPop(gst.ClockTimeNone)
|
||||
switch msg.Type() {
|
||||
|
||||
// When we use this method of popping from the bus (instead of a Watch), we own a
|
||||
|
@@ -18,7 +18,6 @@ gboolean cgoSeekDataCb (GstAppSrc *src, guint64 offset, gpointer user_data) {
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gst/go-gst/gst"
|
||||
@@ -91,12 +90,10 @@ func (a *Source) GetCurrentLevelBytes() uint64 {
|
||||
var gstClockTimeNone C.GstClockTime = 0xffffffffffffffff
|
||||
|
||||
// GetDuration gets the duration of the stream in nanoseconds. A negative value means that the duration is not known.
|
||||
func (a *Source) GetDuration() time.Duration {
|
||||
func (a *Source) GetDuration() gst.ClockTime {
|
||||
dur := C.gst_app_src_get_duration(a.Instance())
|
||||
if dur == gstClockTimeNone {
|
||||
return gst.ClockTimeNone
|
||||
}
|
||||
return time.Duration(uint64(dur)) * time.Nanosecond
|
||||
|
||||
return gst.ClockTime(dur)
|
||||
}
|
||||
|
||||
// GetEmitSignals checks if appsrc will emit the "new-preroll" and "new-buffer" signals.
|
||||
@@ -189,8 +186,8 @@ func (a *Source) SetCaps(caps *gst.Caps) {
|
||||
|
||||
// SetDuration sets the duration of the source stream. You should call
|
||||
// this if the value is known.
|
||||
func (a *Source) SetDuration(dur time.Duration) {
|
||||
C.gst_app_src_set_duration((*C.GstAppSrc)(a.Instance()), C.GstClockTime(dur.Nanoseconds()))
|
||||
func (a *Source) SetDuration(dur gst.ClockTime) {
|
||||
C.gst_app_src_set_duration((*C.GstAppSrc)(a.Instance()), C.GstClockTime(dur))
|
||||
}
|
||||
|
||||
// SetEmitSignals makes appsrc emit the "new-preroll" and "new-buffer" signals. This option is by default disabled because signal emission
|
||||
|
@@ -10,7 +10,6 @@ package gst
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gst/go-glib/glib"
|
||||
@@ -224,7 +223,7 @@ func goClockCb(gclock *C.GstClock, clockTime C.GstClockTime, clockID C.GstClockI
|
||||
}
|
||||
|
||||
clock := wrapClock(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gclock))})
|
||||
return gboolean(cb(clock, time.Duration(clockTime)))
|
||||
return gboolean(cb(clock, ClockTime(clockTime)))
|
||||
}
|
||||
|
||||
//export goPluginInit
|
||||
|
@@ -38,18 +38,11 @@ const (
|
||||
type ClockTimeDiff int64
|
||||
|
||||
// ClockTimeNone means infinite timeout or an empty value
|
||||
var ClockTimeNone time.Duration = time.Duration(-1)
|
||||
var ClockTimeNone ClockTime = C.GST_CLOCK_TIME_NONE
|
||||
|
||||
// BufferOffsetNone is a var for no-offset return results.
|
||||
var BufferOffsetNone time.Duration = time.Duration(-1)
|
||||
|
||||
var (
|
||||
// ClockTimeNone means infinite timeout (unsigned representation of -1) or an otherwise unknown value.
|
||||
gstClockTimeNone C.GstClockTime = 0xffffffffffffffff
|
||||
// // BufferOffsetNone is a constant for no-offset return results.
|
||||
// gstBufferOffsetNone C.GstClockTime = 0xffffffffffffffff
|
||||
)
|
||||
|
||||
// ClockEntryType wraps GstClockEntryType
|
||||
type ClockEntryType int
|
||||
|
||||
|
30
gst/control_binding.go
Normal file
30
gst/control_binding.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package gst
|
||||
|
||||
// #include "gst.go.h"
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gst/go-glib/glib"
|
||||
)
|
||||
|
||||
type ControlBinding struct{ *Object }
|
||||
|
||||
func (cb *ControlBinding) Instance() *C.GstControlBinding {
|
||||
return C.toGstControlBinding(cb.Unsafe())
|
||||
}
|
||||
|
||||
type DirectControlBinding struct{ ControlBinding }
|
||||
|
||||
func NewDirectControlBinding(obj *Object, prop string, csource *InterpolationControlSource) *DirectControlBinding {
|
||||
cprop := C.CString(prop)
|
||||
defer C.free(unsafe.Pointer(cprop))
|
||||
|
||||
cbinding := C.gst_direct_control_binding_new(obj.Instance(), cprop, csource.Instance())
|
||||
|
||||
return &DirectControlBinding{
|
||||
ControlBinding: ControlBinding{
|
||||
Object: wrapObject(glib.TransferNone(unsafe.Pointer(cbinding))),
|
||||
},
|
||||
}
|
||||
}
|
27
gst/control_source.go
Normal file
27
gst/control_source.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package gst
|
||||
|
||||
// #include "gst.go.h"
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gst/go-glib/glib"
|
||||
)
|
||||
|
||||
type InterpolationControlSource struct{ *Object }
|
||||
|
||||
func (cs *InterpolationControlSource) Instance() *C.GstControlSource {
|
||||
return C.toGstControlSource(cs.Unsafe())
|
||||
}
|
||||
|
||||
func NewInterpolationControlSource() *InterpolationControlSource {
|
||||
cCs := C.gst_interpolation_control_source_new()
|
||||
|
||||
return &InterpolationControlSource{
|
||||
Object: wrapObject(glib.TransferNone(unsafe.Pointer(cCs))),
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *InterpolationControlSource) SetTimedValue(time ClockTime, value float64) {
|
||||
C.gst_timed_value_control_source_set(C.toGstTimedValueControlSource(cs.Unsafe()), C.ulong(time), C.double(value))
|
||||
}
|
@@ -42,6 +42,9 @@ GstTask * toGstTask (void *p) { return (GST_TASK_CAST(
|
||||
GstTaskPool * toGstTaskPool (void *p) { return (GST_TASK_POOL_CAST(p)); }
|
||||
GstURIHandler * toGstURIHandler (void *p) { return (GST_URI_HANDLER(p)); }
|
||||
GstUri * toGstURI (void *p) { return (GST_URI(p)); }
|
||||
GstControlBinding * toGstControlBinding (void *p) { return (GST_CONTROL_BINDING(p)); }
|
||||
GstControlSource * toGstControlSource (void *p) { return (GST_CONTROL_SOURCE(p)); }
|
||||
GstTimedValueControlSource * toGstTimedValueControlSource (void *p) { return (GST_TIMED_VALUE_CONTROL_SOURCE(p)); }
|
||||
|
||||
/* Buffer Utilities */
|
||||
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/base.h>
|
||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||
#include <gst/controller/gstdirectcontrolbinding.h>
|
||||
|
||||
typedef struct _PadDestroyNotifyInfo {
|
||||
gpointer pad_ptr;
|
||||
@@ -56,6 +58,9 @@ extern GstTask * toGstTask (void *p);
|
||||
extern GstTaskPool * toGstTaskPool (void *p);
|
||||
extern GstURIHandler * toGstURIHandler (void *p);
|
||||
extern GstUri * toGstURI (void *p);
|
||||
extern GstControlBinding * toGstControlBinding (void *p);
|
||||
extern GstControlSource * toGstControlSource (void *p);
|
||||
extern GstTimedValueControlSource * toGstTimedValueControlSource (void *p);
|
||||
|
||||
/* Buffer Utilities */
|
||||
|
||||
|
@@ -176,12 +176,10 @@ func (b *Buffer) Bytes() []byte {
|
||||
// PresentationTimestamp returns the presentation timestamp of the buffer, or a negative duration
|
||||
// if not known or relevant. This value contains the timestamp when the media should be
|
||||
// presented to the user.
|
||||
func (b *Buffer) PresentationTimestamp() time.Duration {
|
||||
func (b *Buffer) PresentationTimestamp() ClockTime {
|
||||
pts := b.Instance().pts
|
||||
if pts == gstClockTimeNone {
|
||||
return ClockTimeNone
|
||||
}
|
||||
return time.Duration(pts)
|
||||
|
||||
return ClockTime(pts)
|
||||
}
|
||||
|
||||
// SetPresentationTimestamp sets the presentation timestamp on the buffer.
|
||||
@@ -192,22 +190,18 @@ func (b *Buffer) SetPresentationTimestamp(dur time.Duration) {
|
||||
|
||||
// DecodingTimestamp returns the decoding timestamp of the buffer, or a negative duration if not known
|
||||
// or relevant. This value contains the timestamp when the media should be processed.
|
||||
func (b *Buffer) DecodingTimestamp() time.Duration {
|
||||
func (b *Buffer) DecodingTimestamp() ClockTime {
|
||||
dts := b.Instance().dts
|
||||
if dts == gstClockTimeNone {
|
||||
return ClockTimeNone
|
||||
}
|
||||
return time.Duration(dts)
|
||||
|
||||
return ClockTime(dts)
|
||||
}
|
||||
|
||||
// Duration returns the length of the data inside this buffer, or a negative duration if not known
|
||||
// or relevant.
|
||||
func (b *Buffer) Duration() time.Duration {
|
||||
func (b *Buffer) Duration() ClockTime {
|
||||
dur := b.Instance().duration
|
||||
if dur == gstClockTimeNone {
|
||||
return ClockTimeNone
|
||||
}
|
||||
return time.Duration(dur)
|
||||
|
||||
return ClockTime(dur)
|
||||
}
|
||||
|
||||
// SetDuration sets the duration on the buffer.
|
||||
@@ -287,7 +281,7 @@ func (b *Buffer) AddProtectionMeta(info *Structure) *ProtectionMeta {
|
||||
type ReferenceTimestampMeta struct {
|
||||
Parent *Meta
|
||||
Reference *Caps
|
||||
Timestamp, Duration time.Duration
|
||||
Timestamp, Duration ClockTime
|
||||
}
|
||||
|
||||
// AddReferenceTimestampMeta adds a ReferenceTimestampMeta to this buffer that holds a
|
||||
@@ -295,21 +289,16 @@ type ReferenceTimestampMeta struct {
|
||||
//
|
||||
// See the documentation of GstReferenceTimestampMeta for details.
|
||||
// https://gstreamer.freedesktop.org/documentation/gstreamer/gstbuffer.html?gi-language=c#GstReferenceTimestampMeta
|
||||
func (b *Buffer) AddReferenceTimestampMeta(ref *Caps, timestamp, duration time.Duration) *ReferenceTimestampMeta {
|
||||
durClockTime := C.GstClockTime(ClockTimeNone)
|
||||
if duration > time.Duration(0) {
|
||||
durClockTime = C.GstClockTime(duration.Nanoseconds())
|
||||
}
|
||||
tsClockTime := C.GstClockTime(timestamp.Nanoseconds())
|
||||
meta := C.gst_buffer_add_reference_timestamp_meta(b.Instance(), ref.Instance(), tsClockTime, durClockTime)
|
||||
func (b *Buffer) AddReferenceTimestampMeta(ref *Caps, timestamp, duration ClockTime) *ReferenceTimestampMeta {
|
||||
meta := C.gst_buffer_add_reference_timestamp_meta(b.Instance(), ref.Instance(), C.GstClockTime(timestamp), C.GstClockTime(duration))
|
||||
if meta == nil {
|
||||
return nil
|
||||
}
|
||||
return &ReferenceTimestampMeta{
|
||||
Parent: wrapMeta(&meta.parent),
|
||||
Reference: wrapCaps(meta.reference),
|
||||
Timestamp: time.Duration(meta.timestamp),
|
||||
Duration: time.Duration(meta.duration),
|
||||
Timestamp: ClockTime(meta.timestamp),
|
||||
Duration: ClockTime(meta.duration),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,8 +491,8 @@ func (b *Buffer) GetReferenceTimestampMeta(caps *Caps) *ReferenceTimestampMeta {
|
||||
}
|
||||
refMeta := &ReferenceTimestampMeta{
|
||||
Parent: wrapMeta(&meta.parent),
|
||||
Timestamp: time.Duration(meta.timestamp),
|
||||
Duration: time.Duration(meta.duration),
|
||||
Timestamp: ClockTime(meta.timestamp),
|
||||
Duration: ClockTime(meta.duration),
|
||||
}
|
||||
if meta.reference != nil {
|
||||
refMeta.Reference = wrapCaps(meta.reference)
|
||||
|
@@ -97,8 +97,8 @@ func (b *Bus) AddSignalWatch() { C.gst_bus_add_signal_watch(b.Instance()) }
|
||||
//
|
||||
// It is much safer and easier to use the AddWatch or other polling functions. Only use this method if you
|
||||
// are unable to also run a MainLoop, or for convenience sake.
|
||||
func (b *Bus) PopMessage(timeout int) *Message {
|
||||
return b.TimedPop(time.Duration(timeout) * time.Second)
|
||||
func (b *Bus) PopMessage(timeout ClockTime) *Message {
|
||||
return b.TimedPop(timeout)
|
||||
}
|
||||
|
||||
// BlockPopMessage blocks until a message is available on the bus and then returns it.
|
||||
@@ -315,15 +315,9 @@ func (b *Bus) SetSyncHandler(f BusSyncHandler) {
|
||||
|
||||
// TimedPop gets a message from the bus, waiting up to the specified timeout. Unref returned messages after usage.
|
||||
//
|
||||
// If timeout is 0, this function behaves like Pop. If timeout is < 0, this function will block forever until a message was posted on the bus.
|
||||
func (b *Bus) TimedPop(dur time.Duration) *Message {
|
||||
var cTime C.GstClockTime
|
||||
if dur == ClockTimeNone {
|
||||
cTime = C.GstClockTime(gstClockTimeNone)
|
||||
} else {
|
||||
cTime = C.GstClockTime(dur.Nanoseconds())
|
||||
}
|
||||
msg := C.gst_bus_timed_pop(b.Instance(), cTime)
|
||||
// If timeout is 0, this function behaves like Pop. If timeout is ClockTimeNone, this function will block forever until a message was posted on the bus.
|
||||
func (b *Bus) TimedPop(dur ClockTime) *Message {
|
||||
msg := C.gst_bus_timed_pop(b.Instance(), C.GstClockTime(dur))
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -333,16 +327,10 @@ func (b *Bus) TimedPop(dur time.Duration) *Message {
|
||||
// TimedPopFiltered gets a message from the bus whose type matches the message type mask types, waiting up to the specified timeout
|
||||
// (and discarding any messages that do not match the mask provided).
|
||||
//
|
||||
// If timeout is 0, this function behaves like PopFiltered. If timeout is < 0, this function will block forever until a matching message
|
||||
// If timeout is 0, this function behaves like PopFiltered. If timeout is ClockTimeNone, this function will block forever until a matching message
|
||||
// was posted on the bus.
|
||||
func (b *Bus) TimedPopFiltered(dur time.Duration, msgTypes MessageType) *Message {
|
||||
var cTime C.GstClockTime
|
||||
if dur == ClockTimeNone {
|
||||
cTime = C.GstClockTime(gstClockTimeNone)
|
||||
} else {
|
||||
cTime = C.GstClockTime(dur.Nanoseconds())
|
||||
}
|
||||
msg := C.gst_bus_timed_pop_filtered(b.Instance(), cTime, C.GstMessageType(msgTypes))
|
||||
func (b *Bus) TimedPopFiltered(dur ClockTime, msgTypes MessageType) *Message {
|
||||
msg := C.gst_bus_timed_pop_filtered(b.Instance(), C.GstClockTime(dur), C.GstMessageType(msgTypes))
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
|
101
gst/gst_clock.go
101
gst/gst_clock.go
@@ -20,6 +20,7 @@ void clockDestroyNotify (gpointer user_data)
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
"unsafe"
|
||||
@@ -28,8 +29,28 @@ import (
|
||||
gopointer "github.com/mattn/go-pointer"
|
||||
)
|
||||
|
||||
type ClockTime C.GstClockTime
|
||||
|
||||
func (ct ClockTime) String() string {
|
||||
if ct == ClockTimeNone {
|
||||
return "ClockTimeNone"
|
||||
}
|
||||
|
||||
return fmt.Sprint(uint64(ct))
|
||||
}
|
||||
|
||||
func (ct ClockTime) AsDuration() *time.Duration {
|
||||
if ct == ClockTimeNone {
|
||||
return nil
|
||||
}
|
||||
|
||||
dur := time.Duration(uint64(ct))
|
||||
|
||||
return &dur
|
||||
}
|
||||
|
||||
// ClockCallback is the prototype of a clock callback function.
|
||||
type ClockCallback func(clock *Clock, clockTime time.Duration) bool
|
||||
type ClockCallback func(clock *Clock, clockTime ClockTime) bool
|
||||
|
||||
// ClockID is a go wrapper around a GstClockID.
|
||||
type ClockID struct {
|
||||
@@ -46,8 +67,8 @@ func (c *ClockID) GetClock() *Clock {
|
||||
}
|
||||
|
||||
// GetTime returns the time for this ClockID
|
||||
func (c *ClockID) GetTime() time.Duration {
|
||||
return time.Duration(C.gst_clock_id_get_time(c.Instance()))
|
||||
func (c *ClockID) GetTime() ClockTime {
|
||||
return ClockTime(C.gst_clock_id_get_time(c.Instance()))
|
||||
}
|
||||
|
||||
// Unschedule cancels an outstanding request with id. This can either be an outstanding async notification or a pending sync notification.
|
||||
@@ -89,7 +110,7 @@ func (c *ClockID) Wait() (ret ClockReturn, jitter ClockTimeDiff) {
|
||||
//
|
||||
// id := clock.NewSingleShotID(gst.ClockTime(1000000000)) // 1 second
|
||||
//
|
||||
// id.WaitAsync(func(clock *gst.Clock, clockTime time.Duration) bool {
|
||||
// id.WaitAsync(func(clock *gst.Clock, clockTime ClockTime) bool {
|
||||
// fmt.Println("Single shot triggered at", clockTime.Nanoseconds())
|
||||
// pipeline.SetState(gst.StateNull)
|
||||
// return true
|
||||
@@ -143,7 +164,7 @@ func (c *Clock) Instance() *C.GstClock { return C.toGstClock(c.Unsafe()) }
|
||||
//
|
||||
// If this functions returns TRUE, the float will contain the correlation coefficient of the interpolation. A value of 1.0 means
|
||||
// a perfect regression was performed. This value can be used to control the sampling frequency of the master and slave clocks.
|
||||
func (c *Clock) AddObservation(slaveTime, masterTime time.Duration) (bool, float64) {
|
||||
func (c *Clock) AddObservation(slaveTime, masterTime ClockTime) (bool, float64) {
|
||||
var out C.gdouble
|
||||
ok := gobool(C.gst_clock_add_observation(
|
||||
c.Instance(),
|
||||
@@ -158,7 +179,7 @@ func (c *Clock) AddObservation(slaveTime, masterTime time.Duration) (bool, float
|
||||
// result of the master clock estimation, without updating the internal calibration.
|
||||
//
|
||||
// The caller can then take the results and call SetCalibration with the values, or some modified version of them.
|
||||
func (c *Clock) AddObservationUnapplied(slaveTime, masterTime time.Duration) (ok bool, rSquared float64, internalTime, externalTime, rateNum, rateDenom time.Duration) {
|
||||
func (c *Clock) AddObservationUnapplied(slaveTime, masterTime ClockTime) (ok bool, rSquared float64, internalTime, externalTime, rateNum, rateDenom ClockTime) {
|
||||
var ginternal, gexternal, grateNum, grateDenom C.GstClockTime
|
||||
var grSquared C.gdouble
|
||||
ok = gobool(C.gst_clock_add_observation_unapplied(
|
||||
@@ -167,7 +188,7 @@ func (c *Clock) AddObservationUnapplied(slaveTime, masterTime time.Duration) (ok
|
||||
C.GstClockTime(masterTime),
|
||||
&grSquared, &ginternal, &gexternal, &grateNum, &grateDenom,
|
||||
))
|
||||
return ok, float64(grSquared), time.Duration(ginternal), time.Duration(gexternal), time.Duration(grateNum), time.Duration(grateDenom)
|
||||
return ok, float64(grSquared), ClockTime(ginternal), ClockTime(gexternal), ClockTime(grateNum), ClockTime(grateDenom)
|
||||
}
|
||||
|
||||
// AdjustUnlocked converts the given internal clock time to the external time, adjusting for the rate and reference time set with
|
||||
@@ -175,8 +196,8 @@ func (c *Clock) AddObservationUnapplied(slaveTime, masterTime time.Duration) (ok
|
||||
// held and is mainly used by clock subclasses.
|
||||
//
|
||||
// This function is the reverse of UnadjustUnlocked.
|
||||
func (c *Clock) AdjustUnlocked(internal time.Duration) time.Duration {
|
||||
return time.Duration(C.gst_clock_adjust_unlocked(c.Instance(), C.GstClockTime(internal)))
|
||||
func (c *Clock) AdjustUnlocked(internal ClockTime) ClockTime {
|
||||
return ClockTime(C.gst_clock_adjust_unlocked(c.Instance(), C.GstClockTime(internal)))
|
||||
}
|
||||
|
||||
// AdjustWithCalibration converts the given internal_target clock time to the external time, using the passed calibration parameters.
|
||||
@@ -184,8 +205,8 @@ func (c *Clock) AdjustUnlocked(internal time.Duration) time.Duration {
|
||||
// doesn't ensure a monotonically increasing result as AdjustUnlocked does.
|
||||
//
|
||||
// See: https://gstreamer.freedesktop.org/documentation/gstreamer/gstclock.html#gst_clock_adjust_with_calibration
|
||||
func (c *Clock) AdjustWithCalibration(internalTarget, cinternal, cexternal, cnum, cdenom time.Duration) time.Duration {
|
||||
return time.Duration(C.gst_clock_adjust_with_calibration(
|
||||
func (c *Clock) AdjustWithCalibration(internalTarget, cinternal, cexternal, cnum, cdenom ClockTime) ClockTime {
|
||||
return ClockTime(C.gst_clock_adjust_with_calibration(
|
||||
c.Instance(),
|
||||
C.GstClockTime(internalTarget),
|
||||
C.GstClockTime(cinternal),
|
||||
@@ -196,30 +217,26 @@ func (c *Clock) AdjustWithCalibration(internalTarget, cinternal, cexternal, cnum
|
||||
}
|
||||
|
||||
// GetCalibration gets the internal rate and reference time of clock. See gst_clock_set_calibration for more information.
|
||||
func (c *Clock) GetCalibration() (internal, external, rateNum, rateDenom time.Duration) {
|
||||
func (c *Clock) GetCalibration() (internal, external, rateNum, rateDenom ClockTime) {
|
||||
var ginternal, gexternal, grateNum, grateDenom C.GstClockTime
|
||||
C.gst_clock_get_calibration(c.Instance(), &ginternal, &gexternal, &grateNum, &grateDenom)
|
||||
return time.Duration(ginternal), time.Duration(gexternal), time.Duration(grateNum), time.Duration(grateDenom)
|
||||
return ClockTime(ginternal), ClockTime(gexternal), ClockTime(grateNum), ClockTime(grateDenom)
|
||||
}
|
||||
|
||||
// GetTime gets the current time of the given clock in nanoseconds or -1 if invalid.
|
||||
// The time is always monotonically increasing and adjusted according to the current offset and rate.
|
||||
func (c *Clock) GetTime() time.Duration {
|
||||
func (c *Clock) GetTime() ClockTime {
|
||||
res := C.gst_clock_get_time(c.Instance())
|
||||
if res == gstClockTimeNone {
|
||||
return ClockTimeNone
|
||||
}
|
||||
return time.Duration(res)
|
||||
|
||||
return ClockTime(res)
|
||||
}
|
||||
|
||||
// GetInternalTime gets the current internal time of the given clock in nanoseconds
|
||||
// or ClockTimeNone if invalid. The time is returned unadjusted for the offset and the rate.
|
||||
func (c *Clock) GetInternalTime() time.Duration {
|
||||
func (c *Clock) GetInternalTime() ClockTime {
|
||||
res := C.gst_clock_get_internal_time(c.Instance())
|
||||
if res == gstClockTimeNone {
|
||||
return ClockTimeNone
|
||||
}
|
||||
return time.Duration(res)
|
||||
|
||||
return ClockTime(res)
|
||||
}
|
||||
|
||||
// GetMaster returns the master clock that this clock is slaved to or nil when the clock
|
||||
@@ -234,13 +251,13 @@ func (c *Clock) GetMaster() *Clock {
|
||||
|
||||
// GetResolution gets the accuracy of the clock. The accuracy of the clock is the granularity
|
||||
// of the values returned by GetTime.
|
||||
func (c *Clock) GetResolution() time.Duration {
|
||||
return time.Duration(C.gst_clock_get_resolution(c.Instance()))
|
||||
func (c *Clock) GetResolution() ClockTime {
|
||||
return ClockTime(C.gst_clock_get_resolution(c.Instance()))
|
||||
}
|
||||
|
||||
// GetTimeout gets the amount of time that master and slave clocks are sampled.
|
||||
func (c *Clock) GetTimeout() time.Duration {
|
||||
return time.Duration(C.gst_clock_get_timeout(c.Instance()))
|
||||
func (c *Clock) GetTimeout() ClockTime {
|
||||
return ClockTime(C.gst_clock_get_timeout(c.Instance()))
|
||||
}
|
||||
|
||||
// IsSynced returns true if the clock is synced.
|
||||
@@ -248,7 +265,7 @@ func (c *Clock) IsSynced() bool { return gobool(C.gst_clock_is_synced(c.Instance
|
||||
|
||||
// NewPeriodicID gets an ID from clock to trigger a periodic notification. The periodic notifications
|
||||
// will start at time start_time and will then be fired with the given interval. ID should be unreffed after usage.
|
||||
func (c *Clock) NewPeriodicID(startTime, interval time.Duration) *ClockID {
|
||||
func (c *Clock) NewPeriodicID(startTime, interval ClockTime) *ClockID {
|
||||
id := C.gst_clock_new_periodic_id(
|
||||
c.Instance(),
|
||||
C.GstClockTime(startTime),
|
||||
@@ -261,7 +278,7 @@ func (c *Clock) NewPeriodicID(startTime, interval time.Duration) *ClockID {
|
||||
|
||||
// NewSingleShotID gets a ClockID from the clock to trigger a single shot notification at the requested time.
|
||||
// The single shot id should be unreffed after usage.
|
||||
func (c *Clock) NewSingleShotID(at time.Duration) *ClockID {
|
||||
func (c *Clock) NewSingleShotID(at ClockTime) *ClockID {
|
||||
id := C.gst_clock_new_single_shot_id(
|
||||
c.Instance(),
|
||||
C.GstClockTime(at),
|
||||
@@ -273,7 +290,7 @@ func (c *Clock) NewSingleShotID(at time.Duration) *ClockID {
|
||||
|
||||
// PeriodicIDReinit reinitializes the provided periodic id to the provided start time and interval. Does not
|
||||
// / modify the reference count.
|
||||
func (c *Clock) PeriodicIDReinit(clockID *ClockID, startTime, interval time.Duration) bool {
|
||||
func (c *Clock) PeriodicIDReinit(clockID *ClockID, startTime, interval ClockTime) bool {
|
||||
return gobool(C.gst_clock_periodic_id_reinit(
|
||||
c.Instance(),
|
||||
clockID.Instance(),
|
||||
@@ -284,7 +301,7 @@ func (c *Clock) PeriodicIDReinit(clockID *ClockID, startTime, interval time.Dura
|
||||
|
||||
// SetCalibration adjusts the rate and time of clock.
|
||||
// See: https://gstreamer.freedesktop.org/documentation/gstreamer/gstclock.html#gst_clock_set_calibration.
|
||||
func (c *Clock) SetCalibration(internal, external, rateNum, rateDenom time.Duration) {
|
||||
func (c *Clock) SetCalibration(internal, external, rateNum, rateDenom ClockTime) {
|
||||
C.gst_clock_set_calibration(
|
||||
c.Instance(),
|
||||
C.GstClockTime(internal),
|
||||
@@ -311,8 +328,8 @@ func (c *Clock) SetMaster(master *Clock) bool {
|
||||
// SetResolution sets the accuracy of the clock. Some clocks have the possibility to operate with different accuracy
|
||||
// at the expense of more resource usage. There is normally no need to change the default resolution of a clock.
|
||||
// The resolution of a clock can only be changed if the clock has the ClockFlagCanSetResolution flag set.
|
||||
func (c *Clock) SetResolution(resolution time.Duration) time.Duration {
|
||||
return time.Duration(C.gst_clock_set_resolution(c.Instance(), C.GstClockTime(resolution)))
|
||||
func (c *Clock) SetResolution(resolution ClockTime) ClockTime {
|
||||
return ClockTime(C.gst_clock_set_resolution(c.Instance(), C.GstClockTime(resolution)))
|
||||
}
|
||||
|
||||
// SetSynced sets clock to synced and emits the GstClock::synced signal, and wakes up any thread waiting in WaitForSync.
|
||||
@@ -322,12 +339,12 @@ func (c *Clock) SetResolution(resolution time.Duration) time.Duration {
|
||||
func (c *Clock) SetSynced(synced bool) { C.gst_clock_set_synced(c.Instance(), gboolean(synced)) }
|
||||
|
||||
// SetTimeout sets the amount of time, in nanoseconds, to sample master and slave clocks
|
||||
func (c *Clock) SetTimeout(timeout time.Duration) {
|
||||
func (c *Clock) SetTimeout(timeout ClockTime) {
|
||||
C.gst_clock_set_timeout(c.Instance(), C.GstClockTime(timeout))
|
||||
}
|
||||
|
||||
// SingleShotIDReinit reinitializes the provided single shot id to the provided time. Does not modify the reference count.
|
||||
func (c *Clock) SingleShotIDReinit(clockID *ClockID, at time.Duration) bool {
|
||||
func (c *Clock) SingleShotIDReinit(clockID *ClockID, at ClockTime) bool {
|
||||
return gobool(C.gst_clock_single_shot_id_reinit(c.Instance(), clockID.Instance(), C.GstClockTime(at)))
|
||||
}
|
||||
|
||||
@@ -335,14 +352,14 @@ func (c *Clock) SingleShotIDReinit(clockID *ClockID, at time.Duration) bool {
|
||||
// set with SetCalibration. This function should be called with the clock's OBJECT_LOCK held and is mainly used by clock subclasses.
|
||||
//
|
||||
// This function is the reverse of AdjustUnlocked.
|
||||
func (c *Clock) UnadjustUnlocked(external time.Duration) time.Duration {
|
||||
return time.Duration(C.gst_clock_unadjust_unlocked(c.Instance(), C.GstClockTime(external)))
|
||||
func (c *Clock) UnadjustUnlocked(external ClockTime) ClockTime {
|
||||
return ClockTime(C.gst_clock_unadjust_unlocked(c.Instance(), C.GstClockTime(external)))
|
||||
}
|
||||
|
||||
// UnadjustWithCalibration converts the given external_target clock time to the internal time, using the passed calibration parameters.
|
||||
// This function performs the same calculation as UnadjustUnlocked when called using the current calibration parameters.
|
||||
func (c *Clock) UnadjustWithCalibration(externalTarget, cinternal, cexternal, cnum, cdenom time.Duration) time.Duration {
|
||||
return time.Duration(C.gst_clock_unadjust_with_calibration(
|
||||
func (c *Clock) UnadjustWithCalibration(externalTarget, cinternal, cexternal, cnum, cdenom ClockTime) ClockTime {
|
||||
return ClockTime(C.gst_clock_unadjust_with_calibration(
|
||||
c.Instance(),
|
||||
C.GstClockTime(externalTarget),
|
||||
C.GstClockTime(cinternal),
|
||||
@@ -358,12 +375,12 @@ func (c *Clock) UnadjustWithCalibration(externalTarget, cinternal, cexternal, cn
|
||||
// For asynchronous waiting, the GstClock::synced signal can be used.
|
||||
//
|
||||
// This returns immediately with TRUE if ClockFlagNeedsStartupSync is not set on the clock, or if the clock is already synced.
|
||||
func (c *Clock) WaitForSync(timeout time.Duration) bool {
|
||||
func (c *Clock) WaitForSync(timeout ClockTime) bool {
|
||||
return gobool(C.gst_clock_wait_for_sync(c.Instance(), C.GstClockTime(timeout)))
|
||||
}
|
||||
|
||||
// String returns the string representation of this clock value.
|
||||
func (c *Clock) String() string { return c.GetTime().String() }
|
||||
func (c *Clock) String() string { return fmt.Sprintf("%d", c.GetTime()) }
|
||||
|
||||
// InternalString returns the string representation of this clock's internal value.
|
||||
func (c *Clock) InternalString() string { return c.GetInternalTime().String() }
|
||||
func (c *Clock) InternalString() string { return fmt.Sprintf("%d", c.GetInternalTime()) }
|
||||
|
@@ -520,3 +520,39 @@ func (e *Element) GetRequestPad(name string) *Pad {
|
||||
func (e *Element) ReleaseRequestPad(pad *Pad) {
|
||||
C.gst_element_release_request_pad(e.Instance(), pad.Instance())
|
||||
}
|
||||
|
||||
// Set the start time of an element. The start time of the element is the running time of the element
|
||||
// when it last went to the PAUSED state. In READY or after a flushing seek, it is set to 0.
|
||||
//
|
||||
// Toplevel elements like GstPipeline will manage the start_time and base_time on its children.
|
||||
// Setting the start_time to GST_CLOCK_TIME_NONE on such a toplevel element will disable the distribution of the base_time
|
||||
// to the children and can be useful if the application manages the base_time itself, for example if you want to synchronize
|
||||
// capture from multiple pipelines, and you can also ensure that the pipelines have the same clock.
|
||||
//
|
||||
// MT safe.
|
||||
func (e *Element) SetStartTime(startTime ClockTime) {
|
||||
C.gst_element_set_start_time(e.Instance(), C.GstClockTime(startTime))
|
||||
}
|
||||
|
||||
// Returns the start time of the element. The start time is the running time of the clock when this element was last put to PAUSED.
|
||||
// Usually the start_time is managed by a toplevel element such as GstPipeline.
|
||||
// MT safe.
|
||||
func (e *Element) GetStartTime() ClockTime {
|
||||
ctime := C.gst_element_get_start_time(e.Instance())
|
||||
|
||||
return ClockTime(ctime)
|
||||
}
|
||||
|
||||
// Set the base time of an element. The base time is the absolute time of the clock
|
||||
// when this element was last put to PLAYING. Subtracting the base time from the clock time gives the running time of the element.
|
||||
func (e *Element) SetBaseTime(startTime ClockTime) {
|
||||
C.gst_element_set_base_time(e.Instance(), C.GstClockTime(startTime))
|
||||
}
|
||||
|
||||
// Returns the base time of the element. The base time is the absolute time of the clock
|
||||
// when this element was last put to PLAYING. Subtracting the base time from the clock time gives the running time of the element.
|
||||
func (e *Element) GetBaseTime() ClockTime {
|
||||
ctime := C.gst_element_get_base_time(e.Instance())
|
||||
|
||||
return ClockTime(ctime)
|
||||
}
|
||||
|
@@ -28,11 +28,52 @@ func NewElementWithName(factory string, name string) (*Element, error) {
|
||||
elem = C.gst_element_factory_make((*C.gchar)(elemName), (*C.gchar)(cname))
|
||||
}
|
||||
if elem == nil {
|
||||
return nil, fmt.Errorf("Could not create element: %s", factory)
|
||||
return nil, fmt.Errorf("could not create element: %s", factory)
|
||||
}
|
||||
return wrapElement(glib.TransferNone(unsafe.Pointer(elem))), nil
|
||||
}
|
||||
|
||||
// Create a new element of the type defined by the given elementfactory. The supplied list of properties, will be passed at object construction.
|
||||
//
|
||||
// using this results in a free() panic :( DO NOT USE
|
||||
func NewElementWithProperties(factory string, properties map[string]interface{}) (*Element, error) {
|
||||
props := make([]*C.char, 0)
|
||||
values := make([]C.GValue, 0)
|
||||
|
||||
for p, v := range properties {
|
||||
cpropName := C.CString(p)
|
||||
defer C.free(unsafe.Pointer(cpropName))
|
||||
|
||||
props = append(props, cpropName)
|
||||
|
||||
cValue, err := glib.GValue(v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
values = append(values, *(*C.GValue)(cValue.Unsafe()))
|
||||
}
|
||||
|
||||
cfactory := C.CString(factory)
|
||||
defer C.free(unsafe.Pointer(cfactory))
|
||||
|
||||
n := C.uint(len(properties))
|
||||
|
||||
var elem *C.GstElement
|
||||
|
||||
if n > 0 {
|
||||
elem = C.gst_element_factory_make_with_properties(cfactory, n, &props[0], &values[0])
|
||||
} else {
|
||||
elem = C.gst_element_factory_make_with_properties(cfactory, n, nil, nil)
|
||||
}
|
||||
|
||||
if elem == nil {
|
||||
return nil, fmt.Errorf("could not create element: %s", factory)
|
||||
}
|
||||
return wrapElement(glib.TransferFull(unsafe.Pointer(elem))), nil
|
||||
}
|
||||
|
||||
// NewElementMany is a convenience wrapper around building many GstElements in a
|
||||
// single function call. It returns an error if the creation of any element fails. A
|
||||
// slice in the order the names were given is returned.
|
||||
|
@@ -34,20 +34,15 @@ func NewApplicationMessage(src interface{}, structure *Structure) *Message {
|
||||
// RunningTime contains the time of the desired running time when this elements goes to PLAYING.
|
||||
// A value less than 0 for runningTime means that the element has no clock interaction and thus doesn't
|
||||
// care about the running time of the pipeline.
|
||||
func NewAsyncDoneMessage(src interface{}, runningTime time.Duration) *Message {
|
||||
func NewAsyncDoneMessage(src interface{}, runningTime ClockTime) *Message {
|
||||
srcObj := getMessageSourceObj(src)
|
||||
if srcObj == nil {
|
||||
return nil
|
||||
}
|
||||
var cTime C.GstClockTime
|
||||
if runningTime.Nanoseconds() < 0 {
|
||||
cTime = C.GstClockTime(gstClockTimeNone)
|
||||
} else {
|
||||
cTime = C.GstClockTime(runningTime.Nanoseconds())
|
||||
}
|
||||
|
||||
return FromGstMessageUnsafeFull(unsafe.Pointer(C.gst_message_new_async_done(
|
||||
srcObj,
|
||||
cTime,
|
||||
C.GstClockTime(runningTime),
|
||||
)))
|
||||
}
|
||||
|
||||
|
@@ -93,3 +93,7 @@ func (o *Object) Ref() *Object {
|
||||
func (o *Object) Unref() {
|
||||
C.gst_object_unref((C.gpointer)(o.Unsafe()))
|
||||
}
|
||||
|
||||
func (o *Object) AddControlBinding(binding *ControlBinding) {
|
||||
C.gst_object_add_control_binding(o.Instance(), binding.Instance())
|
||||
}
|
||||
|
@@ -78,6 +78,15 @@ func (p *Pipeline) GetPipelineClock() *Clock {
|
||||
return FromGstClockUnsafeFull(unsafe.Pointer(cClock))
|
||||
}
|
||||
|
||||
// Force pipeline to use the given clock. The pipeline will always use the given clock even if new clock providers are added to this pipeline.
|
||||
//
|
||||
// If clock is NULL all clocking will be disabled which will make the pipeline run as fast as possible.
|
||||
//
|
||||
// MT safe.
|
||||
func (p *Pipeline) ForceClock(clock *Clock) {
|
||||
C.gst_pipeline_use_clock(p.Instance(), clock.Instance())
|
||||
}
|
||||
|
||||
/*
|
||||
SetAutoFlushBus can be used to disable automatically flushing the message bus
|
||||
when a pipeline goes to StateNull.
|
||||
|
64
gst/gstnet/gst_ntp_clock.go
Normal file
64
gst/gstnet/gst_ntp_clock.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package gstnet
|
||||
|
||||
// #include "gst.go.h"
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gst/go-gst/gst"
|
||||
)
|
||||
|
||||
// NTP timestamps are realtive to 1. Jan 1900, so we need an offset for 70 Years to be Unix TS compatible
|
||||
const NTPTimeToUnixEpoch = gst.ClockTime(2208988800 * time.Second)
|
||||
|
||||
// NTPClock wraps GstClock
|
||||
type NTPClock struct{ *gst.Clock }
|
||||
|
||||
// ObtainNTPClock returns the default NTPClock. The refcount of the clock will be
|
||||
// increased so you need to unref the clock after usage.
|
||||
func ObtainNTPClock(ctx context.Context, name, address string, port int) (*NTPClock, error) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
||||
caddr := C.CString(address)
|
||||
defer C.free(unsafe.Pointer(caddr))
|
||||
|
||||
currentSystemTime := time.Now().UnixNano() + int64(NTPTimeToUnixEpoch)
|
||||
|
||||
ntpC := &NTPClock{gst.FromGstClockUnsafeFull(unsafe.Pointer(C.gst_ntp_clock_new(cname, caddr, C.gint(port), C.GstClockTime(currentSystemTime))))}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, errors.New("timeout reached while trying to sync")
|
||||
default:
|
||||
if ntpC.IsSynced() {
|
||||
return ntpC, nil
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the current time of the clock
|
||||
//
|
||||
// if you want to access the clocks actual time value, use the underlying NTPClock.Clock.GetTime() instead
|
||||
func (ntp *NTPClock) GetTime() time.Time {
|
||||
// nanos since 1. Jan 1900
|
||||
ntpNanos := NTPClockTime(ntp.Clock.GetTime())
|
||||
|
||||
return ntpNanos.ToDate()
|
||||
}
|
||||
|
||||
type NTPClockTime gst.ClockTime
|
||||
|
||||
func (ct NTPClockTime) ToDate() time.Time {
|
||||
return time.Unix(0, int64(ct)-int64(NTPTimeToUnixEpoch))
|
||||
}
|
||||
|
||||
func NewNTPClockTime(t time.Time) NTPClockTime {
|
||||
return NTPClockTime(t.UnixNano() + int64(NTPTimeToUnixEpoch))
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#cgo pkg-config: gstreamer-1.0
|
||||
#cgo pkg-config: gstreamer-1.0 gstreamer-controller-1.0
|
||||
#cgo CFLAGS: -Wno-deprecated-declarations -Wno-format-security -g -Wall -Wno-unused-variable
|
||||
#cgo LDFLAGS: -lm
|
||||
*/
|
||||
|
Reference in New Issue
Block a user