gondi

package module
v0.0.0-...-601b583 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2024 License: MIT Imports: 9 Imported by: 0

README

gondi - NDI Library wrapper for golang

This is a wrapper for the NDI SDK, for Golang.

It works with Linux and OSX. Windows is not supported yet, as this implementation currently uses purego that does not support Windows.

Installation

Linux

Install the NDI SDK from here. Or download directly from https://downloads.ndi.tv/SDK/NDI_SDK_Linux/Install_NDI_SDK_v5_Linux.tar.gz

OSX

Install the NDI SDK from here.

Tested and working with https://github.com/obs-ndi/obs-ndi/raw/d462e9f83f0e06837a83331b1f71053b2132e751/runtime/libNDI_5.5.3_for_Mac.pkg

Documentation

Overview

Package gondi provides a wrapper for the NDI SDK for Linux, macOS, using purego.

The NDI SDK is available at https://www.ndi.tv/sdk/

The NDI SDK is licensed under the NewTek SDK EULA, which can be found at https://www.ndi.tv/sdk/

NDI® is a registered trademark of Vizrt Group.

Index

Constants

View Source
const (
	SendTimecodeSynthesize int64 = math.MaxInt64
	SendTimecodeEmpty      int64 = 0
)
View Source
const EMPTY_X = 1920
View Source
const EMPTY_Y = 1080

Variables

View Source
var Previews []Preview

Functions

func ClearPreview

func ClearPreview(streamName string)

func ConvertAudioFromInterleaved

func ConvertAudioFromInterleaved(pSrc *AudioFrameV2, pDst *AudioFrameV2)

If your audio frames are interleaved, you can use this function to convert them to planar format. You can also use the frame.SetFromInterleavedArray(data) function to automatically convert an array of float32s in interleaved format to planar format as NDI likes it.

func ConvertAudioToInterleaved

func ConvertAudioToInterleaved(pSrc *AudioFrameV2, pDst *AudioFrameV2)

If your want your audio frames to be interleaved, you can use this function to convert them from planar format. You can also use the frame.GetInterleavedArray() function to get a coverted array of float32s in interleaved format.

func ExtractSourceName

func ExtractSourceName(fullName string) string

func GenerateAlpha

func GenerateAlpha() *image.RGBA

func GetPreview

func GetPreview(streamName string) (*image.RGBA, error)

func GetPreviewIndex

func GetPreviewIndex(streamName string) (int, error)

func GetVersion

func GetVersion() string

Get the version of the NDI library as string

func InitLibrary

func InitLibrary(libraryPath string) error

Initialize the NDI Library, the libraryPath argument is optional and will be automatically set to the default library path for the current platform if empty. This function will panic if it does not find the library, or if it is unable to initialize NDI with the given library. But return error if NDI reports an error initializing.

func SendAlphaFrame

func SendAlphaFrame(sender *SendInstance)

send an alpha frame

func SetPreviewFrame

func SetPreviewFrame(streamName string, frame []byte, width, height int)

Types

type AudioFrameV2

type AudioFrameV2 struct {
	//The sample-rate of this buffer.
	SampleRate int32

	//The number of audio channels.
	NumChannels int32

	//The number of audio samples per channel.
	NumSamples int32

	// The timecode of this frame in 100-nanosecond intervals.
	Timecode int64

	// The audio data as float32 samples
	Data *float32

	// The inter channel stride of the audio channels, in bytes.
	ChannelStride int32

	// Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be in XML format.
	// If you do not want any metadata then you may specify NULL here.
	Metadata *byte

	// This is only valid when receiving a frame and is specified as a 100-nanosecond time that was the exact
	// moment that the frame was submitted by the sending side and is generated by the SDK. If this value is
	// NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.
	Timestamp int64
}

func NewAudioFrameV2

func NewAudioFrameV2() *AudioFrameV2

Allocate a new NDI audio frame object

func NewAudioFrameV2Preallocated

func NewAudioFrameV2Preallocated(numChannels int32, numSamples int32) *AudioFrameV2

Allocate a new NDI audio frame object with preallocated data for holding numChannels * numSamples samples.

func (*AudioFrameV2) GetArray

func (p *AudioFrameV2) GetArray() []float32

Get the audio frames as an array of float32 This is usually stored as planar audio, so the first NumSamples values are the first channel, the next NumSamples values are the second channel, etc. If you need to work with interleaved audio, you can use the GetInterleavedArray() function instead.

func (*AudioFrameV2) GetInterleavedArray

func (p *AudioFrameV2) GetInterleavedArray() []float32

Get the audio frames as an array of float32 This function converts the audio to interleaved audio, so each sample is stored as a single value, and the channels are interleaved.

func (*AudioFrameV2) SetArray

func (p *AudioFrameV2) SetArray(audio []float32)

Set the audio frames from an array of float32 The Data field of the frame needs to be preallocated.

func (*AudioFrameV2) SetFromInterleavedArray

func (p *AudioFrameV2) SetFromInterleavedArray(audio []float32)

This function converts the interleaved audio from the parameter, to planar audio, and stores it in the Data field of the AudioFrameV2. The Data field of the frame needs to be preallocated.

type AudioFrameV3

type AudioFrameV3 struct {
	//The sample-rate of this buffer.
	SampleRate int32

	//The number of audio channels.
	NumChannels int32

	//The number of audio samples per channel.
	NumSamples int32

	// The timecode of this frame in 100-nanosecond intervals.
	Timecode int64

	// The audio data as int16 samples
	Data *byte

	// The inter channel stride of the audio channels, in bytes.
	ChannelStride int32

	// Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be in XML format.
	// If you do not want any metadata then you may specify NULL here.
	Metadata *byte

	// This is only valid when receiving a frame and is specified as a 100-nanosecond time that was the exact
	// moment that the frame was submitted by the sending side and is generated by the SDK. If this value is
	// NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.
	Timestamp int64
}

func NewAudioFrameV3

func NewAudioFrameV3() *AudioFrameV3

Allocate a new NDI audio frame object

type FindInstance

type FindInstance struct {
	// contains filtered or unexported fields
}

Finder instance struct

func NewFindInstance

func NewFindInstance(showLocalSources bool, groups string, extraIPs string) (*FindInstance, error)

Setup a finder instance, initialized groups and extraIPs. ShowLocalSources will control whether local sources are shown or not. The groups property may be empty, and it will use the default from NDI access manager. The extraIPs is only used to manually find sources from known ips on different subnets and is comma separated.

func (*FindInstance) Destroy

func (p *FindInstance) Destroy()

Destroy this finder instance.

func (*FindInstance) GetCurrentSources

func (p *FindInstance) GetCurrentSources() []*Source

Get the current sources from this finder instance. It is recomended to call WaitForSources before this. If you have a UI element to change the source, you should call this function before showing the user the list of sources, to always have the latest list of sources.

func (*FindInstance) WaitForSources

func (p *FindInstance) WaitForSources(timeoutMs uint32) bool

This allows you to wait until the sources on the network have changed. It will return true if the list of sourcess has changed within the timeout, false otherwise. You are not required to call this function, but it is helpful for getting an initial list of sources, and to detect when the list of sources has changed.

type FourCCType

type FourCCType [4]byte
var (
	FourCCTypeRGBA = [4]byte{'R', 'G', 'B', 'A'}
	FourCCTypeRGBX = [4]byte{'R', 'G', 'B', 'X'}
	// YCbCr color space using 4:2:2.
	FourCCTypeUYVY FourCCType = [4]byte{'U', 'Y', 'V', 'Y'}
	// Planar 8bit, 4:4:4:4 video format.
	// Color ordering in memory is blue, green, red, alpha
	FourCCTypeBGRA FourCCType = [4]byte{'B', 'G', 'R', 'A'}
	// Planar 8bit, 4:4:4 video format, packed into 32bit pixels.
	// Color ordering in memory is blue, green, red, 255
	FourCCTypeBGRX FourCCType = [4]byte{'B', 'G', 'R', 'X'}
	// YCbCr + Alpha color space, using 4:2:2:4.
	// In memory there are two separate planes. The first is a regular
	// UYVY 4:2:2 buffer. Immediately following this in memory is a
	// alpha channel buffer.
	FourCCTypeUYVA FourCCType = [4]byte{'U', 'Y', 'V', 'A'}
)

type FrameFormat

type FrameFormat int32

Video frame format

const (
	FrameFormatInterleaved FrameFormat = iota //A fielded frame with the field 0 being on the even lines and field 1 being on the odd lines.
	FrameFormatProgressive                    //A progressive frame.

	//Individual fields.
	FrameFormatField0
	FrameFormatField1
)

type FrameType

type FrameType int32

An enumeration to specify the type of a packet returned by the capture functions

const (
	FrameTypeNone FrameType = iota
	FrameTypeVideo
	FrameTypeAudio
	FrameTypeMetadata
	FrameTypeError

	//This indicates that the settings on this input have changed.
	//For instamce, this value will be returned from NDIlib_recv_capture_v2 and NDIlib_recv_capture
	//when the device is known to have new settings, for instance the web-url has changed ot the device
	//is now known to be a PTZ camera.
	FrameTypeStatusChange FrameType = 100
)

type MetadataFrame

type MetadataFrame struct {
	// The length of the string in UTF8 characters. This includes the NULL terminating character.
	// If this is 0, then the length is assume to be the length of a null terminated string.
	Length int32

	// The timecode of this frame in 100ns intervals.
	Timecode int64

	// The metadata as a UTF8 XML string. This is a NULL terminated string.
	Data *byte
}

func NewMetadataFrame

func NewMetadataFrame(data string) *MetadataFrame

Allocate a new NDIMetadataFrame and initialize it with the specified utf-8 data string.

func (*MetadataFrame) GetData

func (p *MetadataFrame) GetData() string

Get the data of the metadata frame as a utf8-string

type NewRecvInstanceSettings

type NewRecvInstanceSettings struct {
	// Source to connect to
	SourceToConnectTo *Source

	// Your preferred colorspace, default is gondi.RecvColorFormatUYVYBGRA
	ColorFormat RecvColorFormat

	// The bandwidth setting that you wish to use for this video source. Bandwidth
	// controlled by changing both the compression level and the resolution of the source.
	// Default value, and for full quality and all frame types: gondi.RecvBandwidthHighest
	Bandwidth RecvBandwidth

	// When this flag is FALSE, all video that you receive will be progressive. For sources
	// that provide fields, this is de-interlaced on the receiving side (because we cannot change
	// what the up-stream source was actually rendering. This is provided as a convenience to
	// down-stream sources that do not wish to understand fielded video. There is almost no
	// performance impact of using this function.
	// Default is true
	AllowVideoFields bool

	// The name of the ndi receiver to create. This should be named the same way that you
	// would like the source on the network to be named. If this is empty then it will use the filename of your application
	// indexed with the number of the instance number of this receiver.
	Name string
}

type Preview

type Preview struct {
	StreamName string `json:"streamName"`
	IMG        *image.RGBA
	Width      int
	Height     int
}

type RecvBandwidth

type RecvBandwidth int32

Borrowed from ndi-go/ndi.go

const (
	RecvBandwidthMetadataOnly RecvBandwidth = -10 //Receive metadata.
	RecvBandwidthAudioOnly    RecvBandwidth = 10  //Receive metadata, audio.
	RecvBandwidthLowest       RecvBandwidth = 0   //Receive metadata, audio, video at a lower bandwidth and resolution.
	RecvBandwidthHighest      RecvBandwidth = 100 //Receive metadata, audio, video at full resolution.
)

type RecvColorFormat

type RecvColorFormat int32

Borrowed from ndi-go/ndi.go

const (
	RecvColorFormatBGRXBGRA RecvColorFormat = 0 //No alpha channel: BGRX, Alpha channel: BGRA
	RecvColorFormatUYVYBGRA RecvColorFormat = 1 //No alpha channel: UYVY, Alpha channel: BGRA
	RecvColorFormatRGBXRGBA RecvColorFormat = 2 //No alpha channel: RGBX, Alpha channel: RGBA
	RecvColorFormatUYVYRGBA RecvColorFormat = 3 //No alpha channel: UYVY, Alpha channel: RGBA

	//Read the SDK documentation to understand the pros and cons of this format.
	RecvColorFormatFastest RecvColorFormat = 100
)

type RecvInstance

type RecvInstance struct {
	// contains filtered or unexported fields
}

Receiver instance struct

func NewRecvInstance

func NewRecvInstance(settings *NewRecvInstanceSettings) (*RecvInstance, error)

Allocate a new Receiver, using a NewRecvInstanceSetting struct as parameters

func (*RecvInstance) AddConnectionMetadata

func (p *RecvInstance) AddConnectionMetadata(metadata *MetadataFrame)

Add a connection metadata string to the list of what is sent on each new connection. If someone is already connected then this frame will be sent to them immediately.

func (*RecvInstance) CaptureV2

func (p *RecvInstance) CaptureV2(vf *VideoFrameV2, af *AudioFrameV2, mf *MetadataFrame, timeoutMs uint32) FrameType

This will allow you to receive video, audio and metadata frames from the source you are connected to. Any of the frame pointers can be nil, in which case that type of frame will not be captured. This call can be called on separate threads, so it is possible to have a separate thread for each of video, audio and metadata. This function will return the type of frame that was received, or gondi.FrameTypeNone if no frame was received within the specified timeout.

func (*RecvInstance) CaptureV3

func (p *RecvInstance) CaptureV3(vf *VideoFrameV2, af *AudioFrameV3, mf *MetadataFrame, timeoutMs uint32) FrameType

This will allow you to receive video, audio and metadata frames from the source you are connected to. Any of the frame pointers can be nil, in which case that type of frame will not be captured. This call can be called on separate threads, so it is possible to have a separate thread for each of video, audio and metadata. This function will return the type of frame that was received, or gondi.FrameTypeNone if no frame was received within the specified timeout.

func (*RecvInstance) ClearConnectionMetadata

func (p *RecvInstance) ClearConnectionMetadata()

Connection based metadata is data that is sent automatically each time a new connection is received. You queue all of these up and they are sent on each connection. To reset them you need to clear them all and set them up again.

func (*RecvInstance) Connect

func (p *RecvInstance) Connect(source *Source)

Connect

func (*RecvInstance) Destroy

func (p *RecvInstance) Destroy()

Destroy a receiver instance

func (*RecvInstance) FreeAudioV2

func (p *RecvInstance) FreeAudioV2(af *AudioFrameV2)

Free the buffers returned by capture for audio

func (*RecvInstance) FreeMetadata

func (p *RecvInstance) FreeMetadata(metadata *MetadataFrame)

Free the buffers returned by capture for metadata

func (*RecvInstance) FreeVideoV2

func (p *RecvInstance) FreeVideoV2(vf *VideoFrameV2)

Free the buffers returned by capture for video

func (*RecvInstance) GetPerformance

func (p *RecvInstance) GetPerformance() (total *RecvPerformance, dropped *RecvPerformance)

Get the current amount of total and dropped video, audio and metadata frames. This can be used to determine if you have been calling instace.CaptureV2() fast enough to keep up with the incoming stream.

func (*RecvInstance) SendMetadata

func (p *RecvInstance) SendMetadata(metadata *MetadataFrame) bool

This function will send a meta frame to the source that we are connected too. This returns FALSE if we are not currently connected to anything.

func (*RecvInstance) SetTally

func (p *RecvInstance) SetTally(program bool, preview bool) bool

Set the up-stream tally notifications. This returns FALSE if we are not currently connected to anything. That said, the moment that we do connect to something it will automatically be sent the tally state.

type RecvPerformance

type RecvPerformance struct {
	//The current number of video frames
	VideoFrames int64

	//The current number of audio frames
	AudioFrames int64

	//The current number of metadata frames
	MetadataFrames int64
}

type RoutingInstance

type RoutingInstance struct {
	// contains filtered or unexported fields
}

ROuting instance struct

func NewRoutingInstance

func NewRoutingInstance(name string, groups string) (*RoutingInstance, error)

Setup a routed destination, specified by name and groups. The groups property may be empty, and it will use the default from NDI access manager.

func (*RoutingInstance) Change

func (p *RoutingInstance) Change(source *Source)

Change the source this routing instance is connected to.

func (*RoutingInstance) Clear

func (p *RoutingInstance) Clear()

Clear the current source this routing instance is connected to. Should return black to watchers.

func (*RoutingInstance) Destroy

func (p *RoutingInstance) Destroy()

Destroy this routing instance.

func (*RoutingInstance) Groups

func (p *RoutingInstance) Groups() string

Get the set groups for this instance, to change it, destroy this routing instance and create a new with the correct settings.

func (*RoutingInstance) Name

func (p *RoutingInstance) Name() string

Get the set name of this instance. To change it, destroy this routing instance and create a new with the correct settings.

type SendInstance

type SendInstance struct {
	// contains filtered or unexported fields
}

Sender instance struct

func NewSendInstance

func NewSendInstance(name string, groups string, clockVideo bool, clockAudio bool) (*SendInstance, error)

Set up a sender instance using the specified name and string. Syncronous calls will block on either audio or video frames, or both, depending on the clockVideo and clockAudio parameters, to make sure that the frames are sent at the correct time.

func (*SendInstance) AddConnectionMetadata

func (p *SendInstance) AddConnectionMetadata(metadata *MetadataFrame)

Add a connection metadata string to the list of what is sent on each new connection. If someone is already connected then this string will be sent to them immediately.

func (*SendInstance) Capture

func (p *SendInstance) Capture(metadata *MetadataFrame, timeoutMs uint32) FrameType

This method lets you receive metadata from the other end of the connection. Remember that there might be multiple connections to your sender instance.

func (*SendInstance) ClearConnectionMetadata

func (p *SendInstance) ClearConnectionMetadata()

Connection based metadata is data that is sent automatically each time a new connection is received. You queue all of these up and they are sent on each connection. To reset them you need to clear them all and set them up again.

func (*SendInstance) Destroy

func (p *SendInstance) Destroy() error

Remember to call Destroy() on the instance when you are done with it. This will free up resources and unregister the sender.

func (*SendInstance) GetNumberOfConnections

func (p *SendInstance) GetNumberOfConnections(timeoutMs uint32) int32

Get the current number of receivers connected to this source. This can be used to avoid even rendering when nothing is connected to the video source. which can significantly improve the efficiency if you want to make a lot of sources available on the network. If you specify a timeout that is not 0 then it will wait until there are connections for this amount of time.

func (*SendInstance) GetTally

func (p *SendInstance) GetTally(timeoutMs uint32) (*Tally, bool)

Determine the current tally sate. If you specify a timeout then it will wait until it has changed, otherwise it will simply poll it and return the current tally immediately. The boolean return value is whether anything has actually changed (true) or whether it timed out (false)

func (*SendInstance) SendAudioFrame

func (p *SendInstance) SendAudioFrame(frame *AudioFrameV2)

Send an audio frame. This call is syncronous and will block until the frame has been sent, if you specified clockAudio=true in NewNDISendInstance().

func (*SendInstance) SendAudioFrame16s

func (p *SendInstance) SendAudioFrame16s(frame *AudioFrameV3)

Send an audio frame. This call is syncronous and will block until the frame has been sent, if you specified clockAudio=true in NewNDISendInstance().

func (*SendInstance) SendAudioFrame32f

func (p *SendInstance) SendAudioFrame32f(frame *AudioFrameV3)

Send an audio frame. This call is syncronous and will block until the frame has been sent, if you specified clockAudio=true in NewNDISendInstance().

func (*SendInstance) SendAudioFrameV3

func (p *SendInstance) SendAudioFrameV3(frame *AudioFrameV3)

Send an audio frame. This call is syncronous and will block until the frame has been sent, if you specified clockAudio=true in NewNDISendInstance().

func (*SendInstance) SendMetadataFrame

func (p *SendInstance) SendMetadataFrame(frame *MetadataFrame)

Send a metadata frame

func (*SendInstance) SendVideoFrame

func (p *SendInstance) SendVideoFrame(frame *VideoFrameV2)

Send a video frame. This call is syncronous and will block until the frame has been sent if you specified clockVideo=true in NewNDISendInstance().

func (*SendInstance) SendVideoFrameAsync

func (p *SendInstance) SendVideoFrameAsync(frame *VideoFrameV2)

Send video asynchronously, this call will return immediately, and you need to keep the video frame memory resident until a synchronizing event has been received. Syncronizing events are: - A call to frame.SendVideoFrame() - A call to frame.SendVideoFrameAsync() with a different video frame - A call to frame.SendVideoFrame(nil) - A call to frame.Destroy()

func (*SendInstance) SetFailover

func (p *SendInstance) SetFailover(source *Source)

This will assign a new fail-over source for this video source. What this means is that if this video source was to fail any receivers would automatically switch over to use this source, unless this source then came back online. You can specify nil to clear the source.

type Source

type Source struct {
	// contains filtered or unexported fields
}

func (*Source) Address

func (s *Source) Address() string

Address of the source

func (*Source) Name

func (s *Source) Name() string

Name of the source

func (*Source) Set

func (s *Source) Set(name string, address string)

Set the name and address of the source object

type Tally

type Tally struct {
	// Program tally, usually indicated by red
	Program bool
	// Preview tally, usually indicated by green
	Preview bool
}

type VideoFrameV2

type VideoFrameV2 struct {
	// The resolution of this frame.
	Xres, Yres int32

	// What FourCC describing the type of data for this frame.
	FourCC FourCCType

	// What is the frame rate of this frame.
	// For instance NTSC is 30000,1001 = 30000/1001 = 29.97 fps.
	FrameRateN, FrameRateD int32

	// What is the picture aspect ratio of this frame.
	// For instance 16.0/9.0 = 1.778 is 16:9 video
	// 0 means square pixels.
	PictureAspectRatio float32

	// Is this a fielded frame, or is it progressive.
	FrameFormatType FrameFormat

	// The timecode of this frame in 100ns intervals.
	Timecode int64

	// The video data itself.
	Data *byte

	// The inter line stride of the video data, in bytes.
	LineStride int32

	//Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be
	//in XML format. If you do not want any metadata then you may specify NULL here.
	Metadata *byte

	//This is only valid when receiving a frame and is specified as a 100ns time that was the exact
	//moment that the frame was submitted by the sending side and is generated by the SDK. If this
	//value is NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.
	Timestamp int64
}

func NewVideoFrameV2

func NewVideoFrameV2() *VideoFrameV2

Allocate a new NDI video frame with defaults

Directories

Path Synopsis
examples
receiveread Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL