mirror of
				https://github.com/go-gst/go-gst.git
				synced 2025-10-31 03:26:27 +08:00 
			
		
		
		
	Merge pull request #113 from go-gst/webrtc_support
initial Webrtc(-bin) support
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @@ -4,6 +4,6 @@ go 1.22 | ||||
|  | ||||
| require github.com/mattn/go-pointer v0.0.1 | ||||
|  | ||||
| require github.com/go-gst/go-glib v1.1.0 | ||||
| require github.com/go-gst/go-glib v1.2.0 | ||||
|  | ||||
| require golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect | ||||
|   | ||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,5 +1,7 @@ | ||||
| github.com/go-gst/go-glib v1.1.0 h1:XTGhwk2BWYjW/UZ08y7ojf3iPPRiYtXL0W6vJkXNKFc= | ||||
| github.com/go-gst/go-glib v1.1.0/go.mod h1:JybIYeoHNwCkHGaBf1fHNIaM4sQTrJPkPLsi7dmPNOU= | ||||
| github.com/go-gst/go-glib v1.2.0 h1:IEi5Og63V8YHBprCFiLsesRKSKWuxY0nYOMgbm7P2NI= | ||||
| github.com/go-gst/go-glib v1.2.0/go.mod h1:JybIYeoHNwCkHGaBf1fHNIaM4sQTrJPkPLsi7dmPNOU= | ||||
| github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= | ||||
| github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= | ||||
| golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= | ||||
|   | ||||
| @@ -198,5 +198,11 @@ func marshalPromise(p unsafe.Pointer) (interface{}, error) { | ||||
| 		done: nil, // cannot be awaited if received from FFI | ||||
| 	} | ||||
|  | ||||
| 	prom.Ref() | ||||
|  | ||||
| 	runtime.SetFinalizer(prom, func(p *Promise) { | ||||
| 		p.Unref() | ||||
| 	}) | ||||
|  | ||||
| 	return prom, nil | ||||
| } | ||||
|   | ||||
| @@ -4,10 +4,8 @@ import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"runtime" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| //go:noinline | ||||
| @@ -35,9 +33,7 @@ func awaitGC() { | ||||
| } | ||||
|  | ||||
| func TestPromise(t *testing.T) { | ||||
| 	initOnce.Do(func() { | ||||
| 		Init(nil) | ||||
| 	}) | ||||
| 	Init(nil) | ||||
|  | ||||
| 	prom := NewPromise() | ||||
| 	cprom := prom.Instance() | ||||
| @@ -87,12 +83,8 @@ func TestPromise(t *testing.T) { | ||||
| 	awaitGC() | ||||
| } | ||||
|  | ||||
| var initOnce sync.Once | ||||
|  | ||||
| func TestPromiseMarshal(t *testing.T) { | ||||
| 	initOnce.Do(func() { | ||||
| 		Init(nil) | ||||
| 	}) | ||||
| 	Init(nil) | ||||
|  | ||||
| 	prom := NewPromise() | ||||
|  | ||||
| @@ -102,7 +94,7 @@ func TestPromiseMarshal(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	receivedPromI, err := marshalPromise(unsafe.Pointer(gv.GValue)) | ||||
| 	receivedPromI, err := gv.GoValue() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
|   | ||||
							
								
								
									
										2
									
								
								gst/gstsdp/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								gst/gstsdp/doc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| // gstsdp contains bindings for the gstreamer sdp library. See also https://gstreamer.freedesktop.org/documentation/sdp/index.html | ||||
| package gstsdp | ||||
							
								
								
									
										6
									
								
								gst/gstsdp/gst.go.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								gst/gstsdp/gst.go.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #ifndef __GST_WEBRTC_GO_H__ | ||||
| #define __GST_WEBRTC_GO_H__ | ||||
|  | ||||
| #include <gst/sdp/sdp.h> | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										94
									
								
								gst/gstsdp/message.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								gst/gstsdp/message.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| package gstsdp | ||||
|  | ||||
| // #include "gst.go.h" | ||||
| import "C" | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"runtime" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| type SDPResult C.GstSDPResult | ||||
|  | ||||
| const ( | ||||
| 	SDPResultOk SDPResult = C.GST_SDP_OK | ||||
| 	SDPEinval   SDPResult = C.GST_SDP_EINVAL | ||||
| ) | ||||
|  | ||||
| type Message struct { | ||||
| 	ptr *C.GstSDPMessage | ||||
| } | ||||
|  | ||||
| func wrapSDPMessageAndFinalize(sdp *C.GstSDPMessage) *Message { | ||||
| 	msg := &Message{ | ||||
| 		ptr: sdp, | ||||
| 	} | ||||
|  | ||||
| 	// this requires that we copy the SDP message before passing it to any transfer-ownership function | ||||
| 	runtime.SetFinalizer(msg, func(msg *Message) { | ||||
| 		msg.Free() | ||||
| 	}) | ||||
|  | ||||
| 	return msg | ||||
| } | ||||
|  | ||||
| // NewMessageFromUnsafe creates a new SDP message from a pointer and does not finalize it | ||||
| func NewMessageFromUnsafe(ptr unsafe.Pointer) *Message { | ||||
| 	return &Message{ | ||||
| 		ptr: (*C.GstSDPMessage)(ptr), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| var ErrSDPInvalid = errors.New("invalid SDP") | ||||
|  | ||||
| func ParseSDPMessage(sdp string) (*Message, error) { | ||||
| 	cstr := C.CString(sdp) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
|  | ||||
| 	var msg *C.GstSDPMessage | ||||
|  | ||||
| 	res := SDPResult(C.gst_sdp_message_new_from_text(cstr, &msg)) | ||||
|  | ||||
| 	if res != SDPResultOk || msg == nil { | ||||
| 		return nil, ErrSDPInvalid | ||||
| 	} | ||||
|  | ||||
| 	return wrapSDPMessageAndFinalize(msg), nil | ||||
| } | ||||
|  | ||||
| func (msg *Message) String() string { | ||||
| 	cstr := C.gst_sdp_message_as_text(msg.ptr) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
|  | ||||
| 	return C.GoString(cstr) | ||||
| } | ||||
|  | ||||
| // UnownedCopy creates a new copy of the SDP message that will not be finalized | ||||
| // | ||||
| // this is needed to pass the message back to C where C takes ownership of the message | ||||
| // | ||||
| // the returned SDP message will leak memory if not freed manually | ||||
| func (msg *Message) UnownedCopy() *Message { | ||||
| 	var newMsg *C.GstSDPMessage | ||||
| 	res := C.gst_sdp_message_copy(msg.ptr, &newMsg) | ||||
|  | ||||
| 	if res != C.GST_SDP_OK || newMsg == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return &Message{ | ||||
| 		ptr: newMsg, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Free frees the SDP message. | ||||
| // | ||||
| // This is called automatically when the object is garbage collected. | ||||
| func (msg *Message) Free() { | ||||
| 	C.gst_sdp_message_free(msg.ptr) | ||||
| 	msg.ptr = nil | ||||
| } | ||||
|  | ||||
| func (msg *Message) Instance() unsafe.Pointer { | ||||
| 	return unsafe.Pointer(msg.ptr) | ||||
| } | ||||
							
								
								
									
										7
									
								
								gst/gstsdp/pkg_config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								gst/gstsdp/pkg_config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| package gstsdp | ||||
|  | ||||
| /* | ||||
| #cgo pkg-config: gstreamer-sdp-1.0 | ||||
| #cgo CFLAGS: -Wno-deprecated-declarations -g -Wall | ||||
| */ | ||||
| import "C" | ||||
							
								
								
									
										67
									
								
								gst/gstwebrtc/data_channel.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								gst/gstwebrtc/data_channel.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| // #include "gst.go.h" | ||||
| import "C" | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/go-gst/go-glib/glib" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
|  | ||||
| 	tm := []glib.TypeMarshaler{ | ||||
| 		{T: glib.Type(C.GST_TYPE_WEBRTC_DATA_CHANNEL), F: marshalDataChannel}, | ||||
| 	} | ||||
|  | ||||
| 	glib.RegisterGValueMarshalers(tm) | ||||
| } | ||||
|  | ||||
| // DataChannel is a representation of GstWebRTCDataChannel. See https://gstreamer.freedesktop.org/documentation/webrtclib/gstwebrtc-datachannel.html?gi-language=c | ||||
| // | ||||
| // there is no constructor for DataChannel, you can get it from webrtcbin signals | ||||
| type DataChannel struct { | ||||
| 	*glib.Object | ||||
| } | ||||
|  | ||||
| func (dc *DataChannel) Close() { | ||||
| 	C.gst_webrtc_data_channel_close((*C.GstWebRTCDataChannel)(dc.Native())) | ||||
| } | ||||
|  | ||||
| func (dc *DataChannel) SendData(data []byte) error { | ||||
| 	var gerr *C.GError | ||||
|  | ||||
| 	addr := unsafe.SliceData(data) | ||||
|  | ||||
| 	cbytes := C.g_bytes_new(C.gconstpointer(addr), C.gsize(len(data))) | ||||
| 	defer C.g_bytes_unref(cbytes) | ||||
|  | ||||
| 	C.gst_webrtc_data_channel_send_data_full((*C.GstWebRTCDataChannel)(dc.Native()), cbytes, &gerr) | ||||
|  | ||||
| 	if gerr != nil { | ||||
| 		defer C.g_error_free((*C.GError)(gerr)) | ||||
| 		errMsg := C.GoString(gerr.message) | ||||
| 		return errors.New(errMsg) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ToGValue implements glib.ValueTransformer | ||||
| func (dc *DataChannel) ToGValue() (*glib.Value, error) { | ||||
| 	val, err := glib.ValueInit(glib.Type(C.GST_TYPE_WEBRTC_DATA_CHANNEL)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	val.SetInstance(unsafe.Pointer(dc.GObject)) | ||||
| 	return val, nil | ||||
| } | ||||
|  | ||||
| func marshalDataChannel(p unsafe.Pointer) (interface{}, error) { | ||||
| 	c := C.g_value_get_object((*C.GValue)(p)) | ||||
|  | ||||
| 	return &DataChannel{ | ||||
| 		Object: glib.Take(unsafe.Pointer(c)), | ||||
| 	}, nil | ||||
| } | ||||
							
								
								
									
										42
									
								
								gst/gstwebrtc/data_channel_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								gst/gstwebrtc/data_channel_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-gst/go-gst/gst" | ||||
| ) | ||||
|  | ||||
| func TestDataChannelMarshal(t *testing.T) { | ||||
| 	gst.Init(nil) | ||||
|  | ||||
| 	// hack to get a valid glib.Object | ||||
| 	el, err := gst.NewElement("webrtcbin") | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	dc := &DataChannel{ | ||||
| 		Object: el.Object.Object, | ||||
| 	} | ||||
|  | ||||
| 	gv, err := dc.ToGValue() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	dcI, err := gv.GoValue() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	dc, ok := dcI.(*DataChannel) | ||||
|  | ||||
| 	if !ok { | ||||
| 		t.Error("Failed to convert to DataChannel") | ||||
| 	} | ||||
|  | ||||
| 	_ = dc | ||||
| } | ||||
							
								
								
									
										2
									
								
								gst/gstwebrtc/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								gst/gstwebrtc/doc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| // gstwebrtc contains bindings for the gstreamer webrtclib. See also https://gstreamer.freedesktop.org/documentation/webrtclib/index.html | ||||
| package gstwebrtc | ||||
							
								
								
									
										507
									
								
								gst/gstwebrtc/enums.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										507
									
								
								gst/gstwebrtc/enums.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,507 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| // #include "gst.go.h" | ||||
| import "C" | ||||
|  | ||||
| type BundlePolicy C.GstWebRTCBundlePolicy | ||||
|  | ||||
| const ( | ||||
| 	BUNDLE_POLICY_NONE       BundlePolicy = C.GST_WEBRTC_BUNDLE_POLICY_NONE       // none | ||||
| 	BUNDLE_POLICY_BALANCED   BundlePolicy = C.GST_WEBRTC_BUNDLE_POLICY_BALANCED   // balanced | ||||
| 	BUNDLE_POLICY_MAX_COMPAT BundlePolicy = C.GST_WEBRTC_BUNDLE_POLICY_MAX_COMPAT // max-compat | ||||
| 	BUNDLE_POLICY_MAX_BUNDLE BundlePolicy = C.GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE // max-bundle | ||||
| ) | ||||
|  | ||||
| func (e BundlePolicy) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_BUNDLE_POLICY_NONE: | ||||
| 		return "none" | ||||
| 	case C.GST_WEBRTC_BUNDLE_POLICY_BALANCED: | ||||
| 		return "balanced" | ||||
| 	case C.GST_WEBRTC_BUNDLE_POLICY_MAX_COMPAT: | ||||
| 		return "max-compat" | ||||
| 	case C.GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE: | ||||
| 		return "max-bundle" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type DTLSSetup C.GstWebRTCDTLSSetup | ||||
|  | ||||
| const ( | ||||
| 	DTLS_SETUP_NONE    DTLSSetup = C.GST_WEBRTC_DTLS_SETUP_NONE    // none | ||||
| 	DTLS_SETUP_ACTPASS DTLSSetup = C.GST_WEBRTC_DTLS_SETUP_ACTPASS // actpass | ||||
| 	DTLS_SETUP_ACTIVE  DTLSSetup = C.GST_WEBRTC_DTLS_SETUP_ACTIVE  // sendonly | ||||
| 	DTLS_SETUP_PASSIVE DTLSSetup = C.GST_WEBRTC_DTLS_SETUP_PASSIVE // recvonly | ||||
| ) | ||||
|  | ||||
| func (e DTLSSetup) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_DTLS_SETUP_NONE: | ||||
| 		return "none" | ||||
| 	case C.GST_WEBRTC_DTLS_SETUP_ACTPASS: | ||||
| 		return "actpass" | ||||
| 	case C.GST_WEBRTC_DTLS_SETUP_ACTIVE: | ||||
| 		return "sendonly" | ||||
| 	case C.GST_WEBRTC_DTLS_SETUP_PASSIVE: | ||||
| 		return "recvonly" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type DTLSTransportState C.GstWebRTCDTLSTransportState | ||||
|  | ||||
| const ( | ||||
| 	DTLS_TRANSPORT_STATE_NEW        DTLSTransportState = C.GST_WEBRTC_DTLS_TRANSPORT_STATE_NEW        // new | ||||
| 	DTLS_TRANSPORT_STATE_CLOSED     DTLSTransportState = C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CLOSED     // closed | ||||
| 	DTLS_TRANSPORT_STATE_FAILED     DTLSTransportState = C.GST_WEBRTC_DTLS_TRANSPORT_STATE_FAILED     // failed | ||||
| 	DTLS_TRANSPORT_STATE_CONNECTING DTLSTransportState = C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTING // connecting | ||||
| 	DTLS_TRANSPORT_STATE_CONNECTED  DTLSTransportState = C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED  // connected | ||||
| ) | ||||
|  | ||||
| func (e DTLSTransportState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_DTLS_TRANSPORT_STATE_NEW: | ||||
| 		return "new" | ||||
| 	case C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	case C.GST_WEBRTC_DTLS_TRANSPORT_STATE_FAILED: | ||||
| 		return "failed" | ||||
| 	case C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTING: | ||||
| 		return "connecting" | ||||
| 	case C.GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED: | ||||
| 		return "connected" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type DataChannelState C.GstWebRTCDataChannelState | ||||
|  | ||||
| const ( | ||||
| 	DATA_CHANNEL_STATE_CONNECTING DataChannelState = C.GST_WEBRTC_DATA_CHANNEL_STATE_CONNECTING // connecting | ||||
| 	DATA_CHANNEL_STATE_OPEN       DataChannelState = C.GST_WEBRTC_DATA_CHANNEL_STATE_OPEN       // open | ||||
| 	DATA_CHANNEL_STATE_CLOSING    DataChannelState = C.GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING    // closing | ||||
| 	DATA_CHANNEL_STATE_CLOSED     DataChannelState = C.GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED     // closed | ||||
| ) | ||||
|  | ||||
| func (e DataChannelState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_DATA_CHANNEL_STATE_CONNECTING: | ||||
| 		return "connecting" | ||||
| 	case C.GST_WEBRTC_DATA_CHANNEL_STATE_OPEN: | ||||
| 		return "open" | ||||
| 	case C.GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING: | ||||
| 		return "closing" | ||||
| 	case C.GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type Error C.GstWebRTCError | ||||
|  | ||||
| const ( | ||||
| 	ERROR_DATA_CHANNEL_FAILURE           Error = C.GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE           // data-channel-failure | ||||
| 	ERROR_DTLS_FAILURE                   Error = C.GST_WEBRTC_ERROR_DTLS_FAILURE                   // dtls-failure | ||||
| 	ERROR_FINGERPRINT_FAILURE            Error = C.GST_WEBRTC_ERROR_FINGERPRINT_FAILURE            // fingerprint-failure | ||||
| 	ERROR_SCTP_FAILURE                   Error = C.GST_WEBRTC_ERROR_SCTP_FAILURE                   // sctp-failure | ||||
| 	ERROR_SDP_SYNTAX_ERROR               Error = C.GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR               // sdp-syntax-error | ||||
| 	ERROR_HARDWARE_ENCODER_NOT_AVAILABLE Error = C.GST_WEBRTC_ERROR_HARDWARE_ENCODER_NOT_AVAILABLE // hardware-encoder-not-available | ||||
| 	ERROR_ENCODER_ERROR                  Error = C.GST_WEBRTC_ERROR_ENCODER_ERROR                  // encoder-error | ||||
| 	ERROR_INVALID_STATE                  Error = C.GST_WEBRTC_ERROR_INVALID_STATE                  // invalid-state | ||||
| 	ERROR_INTERNAL_FAILURE               Error = C.GST_WEBRTC_ERROR_INTERNAL_FAILURE               // internal-failure | ||||
| 	ERROR_INVALID_MODIFICATION           Error = C.GST_WEBRTC_ERROR_INVALID_MODIFICATION           // invalid-modification | ||||
| 	ERROR_TYPE_ERROR                     Error = C.GST_WEBRTC_ERROR_TYPE_ERROR                     // type-error | ||||
| ) | ||||
|  | ||||
| func (e Error) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE: | ||||
| 		return "data-channel-failure" | ||||
| 	case C.GST_WEBRTC_ERROR_DTLS_FAILURE: | ||||
| 		return "dtls-failure" | ||||
| 	case C.GST_WEBRTC_ERROR_FINGERPRINT_FAILURE: | ||||
| 		return "fingerprint-failure" | ||||
| 	case C.GST_WEBRTC_ERROR_SCTP_FAILURE: | ||||
| 		return "sctp-failure" | ||||
| 	case C.GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR: | ||||
| 		return "sdp-syntax-error" | ||||
| 	case C.GST_WEBRTC_ERROR_HARDWARE_ENCODER_NOT_AVAILABLE: | ||||
| 		return "hardware-encoder-not-available" | ||||
| 	case C.GST_WEBRTC_ERROR_ENCODER_ERROR: | ||||
| 		return "encoder-error" | ||||
| 	case C.GST_WEBRTC_ERROR_INVALID_STATE: | ||||
| 		return "invalid-state" | ||||
| 	case C.GST_WEBRTC_ERROR_INTERNAL_FAILURE: | ||||
| 		return "internal-failure" | ||||
| 	case C.GST_WEBRTC_ERROR_INVALID_MODIFICATION: | ||||
| 		return "invalid-modification" | ||||
| 	case C.GST_WEBRTC_ERROR_TYPE_ERROR: | ||||
| 		return "type-error" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type FECType C.GstWebRTCFECType | ||||
|  | ||||
| const ( | ||||
| 	FEC_TYPE_NONE    FECType = C.GST_WEBRTC_FEC_TYPE_NONE    // none | ||||
| 	FEC_TYPE_ULP_RED FECType = C.GST_WEBRTC_FEC_TYPE_ULP_RED // ulpfec + red | ||||
| ) | ||||
|  | ||||
| func (e FECType) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_FEC_TYPE_NONE: | ||||
| 		return "none" | ||||
| 	case C.GST_WEBRTC_FEC_TYPE_ULP_RED: | ||||
| 		return "ulpfec + red" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type ICEComponent C.GstWebRTCICEComponent | ||||
|  | ||||
| //  GST_WEBRTC_ICE_COMPONENT_RTP (0)RTP component | ||||
| // GST_WEBRTC_ICE_COMPONENT_RTCP (1)RTCP component | ||||
|  | ||||
| const ( | ||||
| 	ICE_COMPONENT_RTP  ICEComponent = C.GST_WEBRTC_ICE_COMPONENT_RTP  // RTP component | ||||
| 	ICE_COMPONENT_RTCP ICEComponent = C.GST_WEBRTC_ICE_COMPONENT_RTCP // RTCP component | ||||
| ) | ||||
|  | ||||
| func (e ICEComponent) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ICE_COMPONENT_RTP: | ||||
| 		return "RTP component" | ||||
| 	case C.GST_WEBRTC_ICE_COMPONENT_RTCP: | ||||
| 		return "RTCP component" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type ICEConnectionState C.GstWebRTCICEConnectionState | ||||
|  | ||||
| const ( | ||||
| 	ICE_CONNECTION_STATE_NEW          ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_NEW          // new | ||||
| 	ICE_CONNECTION_STATE_CHECKING     ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING     // checking | ||||
| 	ICE_CONNECTION_STATE_CONNECTED    ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED    // connected | ||||
| 	ICE_CONNECTION_STATE_COMPLETED    ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED    // completed | ||||
| 	ICE_CONNECTION_STATE_FAILED       ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_FAILED       // failed | ||||
| 	ICE_CONNECTION_STATE_DISCONNECTED ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED // disconnected | ||||
| 	ICE_CONNECTION_STATE_CLOSED       ICEConnectionState = C.GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED       // closed | ||||
| ) | ||||
|  | ||||
| func (e ICEConnectionState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_NEW: | ||||
| 		return "new" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING: | ||||
| 		return "checking" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED: | ||||
| 		return "connected" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED: | ||||
| 		return "completed" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_FAILED: | ||||
| 		return "failed" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED: | ||||
| 		return "disconnected" | ||||
| 	case C.GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type ICEGatheringState C.GstWebRTCICEGatheringState | ||||
|  | ||||
| const ( | ||||
| 	ICE_GATHERING_STATE_NEW       ICEGatheringState = C.GST_WEBRTC_ICE_GATHERING_STATE_NEW       // new | ||||
| 	ICE_GATHERING_STATE_GATHERING ICEGatheringState = C.GST_WEBRTC_ICE_GATHERING_STATE_GATHERING // gathering | ||||
| 	ICE_GATHERING_STATE_COMPLETE  ICEGatheringState = C.GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE  // complete | ||||
| ) | ||||
|  | ||||
| func (e ICEGatheringState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ICE_GATHERING_STATE_NEW: | ||||
| 		return "new" | ||||
| 	case C.GST_WEBRTC_ICE_GATHERING_STATE_GATHERING: | ||||
| 		return "gathering" | ||||
| 	case C.GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE: | ||||
| 		return "complete" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type ICERole C.GstWebRTCICERole | ||||
|  | ||||
| const ( | ||||
| 	ICE_ROLE_CONTROLLED  ICERole = C.GST_WEBRTC_ICE_ROLE_CONTROLLED  // controlled | ||||
| 	ICE_ROLE_CONTROLLING ICERole = C.GST_WEBRTC_ICE_ROLE_CONTROLLING // controlling | ||||
| ) | ||||
|  | ||||
| func (e ICERole) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ICE_ROLE_CONTROLLED: | ||||
| 		return "controlled" | ||||
| 	case C.GST_WEBRTC_ICE_ROLE_CONTROLLING: | ||||
| 		return "controlling" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type ICETransportPolicy C.GstWebRTCICETransportPolicy | ||||
|  | ||||
| const ( | ||||
| 	ICE_TRANSPORT_POLICY_ALL   ICETransportPolicy = C.GST_WEBRTC_ICE_TRANSPORT_POLICY_ALL   // all | ||||
| 	ICE_TRANSPORT_POLICY_RELAY ICETransportPolicy = C.GST_WEBRTC_ICE_TRANSPORT_POLICY_RELAY // relay | ||||
| ) | ||||
|  | ||||
| func (e ICETransportPolicy) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_ICE_TRANSPORT_POLICY_ALL: | ||||
| 		return "all" | ||||
| 	case C.GST_WEBRTC_ICE_TRANSPORT_POLICY_RELAY: | ||||
| 		return "relay" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type Kind C.GstWebRTCKind | ||||
|  | ||||
| const ( | ||||
| 	UNKNOWN Kind = C.GST_WEBRTC_KIND_UNKNOWN // unknown | ||||
| 	AUDIO   Kind = C.GST_WEBRTC_KIND_AUDIO   // audio | ||||
| 	VIDEO   Kind = C.GST_WEBRTC_KIND_VIDEO   // video | ||||
| ) | ||||
|  | ||||
| func (e Kind) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_KIND_UNKNOWN: | ||||
| 		return "unknown" | ||||
| 	case C.GST_WEBRTC_KIND_AUDIO: | ||||
| 		return "audio" | ||||
| 	case C.GST_WEBRTC_KIND_VIDEO: | ||||
| 		return "video" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type PeerConnectionState C.GstWebRTCPeerConnectionState | ||||
|  | ||||
| //  GST_WEBRTC_PEER_CONNECTION_STATE_NEW (0)new | ||||
| // GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTING (1)connecting | ||||
| // GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTED (2)connected | ||||
| // GST_WEBRTC_PEER_CONNECTION_STATE_DISCONNECTED (3)disconnected | ||||
| // GST_WEBRTC_PEER_CONNECTION_STATE_FAILED (4)failed | ||||
| // GST_WEBRTC_PEER_CONNECTION_STATE_CLOSED (5)closed | ||||
|  | ||||
| const ( | ||||
| 	PEER_CONNECTION_STATE_NEW          PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_NEW          // new | ||||
| 	PEER_CONNECTION_STATE_CONNECTING   PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTING   // connecting | ||||
| 	PEER_CONNECTION_STATE_CONNECTED    PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTED    // connected | ||||
| 	PEER_CONNECTION_STATE_DISCONNECTED PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_DISCONNECTED // disconnected | ||||
| 	PEER_CONNECTION_STATE_FAILED       PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_FAILED       // failed | ||||
| 	PEER_CONNECTION_STATE_CLOSED       PeerConnectionState = C.GST_WEBRTC_PEER_CONNECTION_STATE_CLOSED       // closed | ||||
| ) | ||||
|  | ||||
| func (e PeerConnectionState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_NEW: | ||||
| 		return "new" | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTING: | ||||
| 		return "connecting" | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_CONNECTED: | ||||
| 		return "connected" | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_DISCONNECTED: | ||||
| 		return "disconnected" | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_FAILED: | ||||
| 		return "failed" | ||||
| 	case C.GST_WEBRTC_PEER_CONNECTION_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type PriorityType C.GstWebRTCPriorityType | ||||
|  | ||||
| const ( | ||||
| 	PRIORITY_TYPE_VERY_LOW PriorityType = C.GST_WEBRTC_PRIORITY_TYPE_VERY_LOW // very-low | ||||
| 	PRIORITY_TYPE_LOW      PriorityType = C.GST_WEBRTC_PRIORITY_TYPE_LOW      // low | ||||
| 	PRIORITY_TYPE_MEDIUM   PriorityType = C.GST_WEBRTC_PRIORITY_TYPE_MEDIUM   // medium | ||||
| 	PRIORITY_TYPE_HIGH     PriorityType = C.GST_WEBRTC_PRIORITY_TYPE_HIGH     // high | ||||
| ) | ||||
|  | ||||
| func (e PriorityType) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_PRIORITY_TYPE_VERY_LOW: | ||||
| 		return "very-low" | ||||
| 	case C.GST_WEBRTC_PRIORITY_TYPE_LOW: | ||||
| 		return "low" | ||||
| 	case C.GST_WEBRTC_PRIORITY_TYPE_MEDIUM: | ||||
| 		return "medium" | ||||
| 	case C.GST_WEBRTC_PRIORITY_TYPE_HIGH: | ||||
| 		return "high" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type RTPTransceiverDirection C.GstWebRTCRTPTransceiverDirection | ||||
|  | ||||
| const ( | ||||
| 	RTP_TRANSCEIVER_DIRECTION_NONE     RTPTransceiverDirection = C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE     // none | ||||
| 	RTP_TRANSCEIVER_DIRECTION_INACTIVE RTPTransceiverDirection = C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE // inactive | ||||
| 	RTP_TRANSCEIVER_DIRECTION_SENDONLY RTPTransceiverDirection = C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY // sendonly | ||||
| 	RTP_TRANSCEIVER_DIRECTION_RECVONLY RTPTransceiverDirection = C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY // recvonly | ||||
| 	RTP_TRANSCEIVER_DIRECTION_SENDRECV RTPTransceiverDirection = C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV // sendrecv | ||||
| ) | ||||
|  | ||||
| func (e RTPTransceiverDirection) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE: | ||||
| 		return "none" | ||||
| 	case C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE: | ||||
| 		return "inactive" | ||||
| 	case C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY: | ||||
| 		return "sendonly" | ||||
| 	case C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY: | ||||
| 		return "recvonly" | ||||
| 	case C.GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV: | ||||
| 		return "sendrecv" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type SCTPTransportState C.GstWebRTCSCTPTransportState | ||||
|  | ||||
| const ( | ||||
| 	SCTP_TRANSPORT_STATE_NEW        SCTPTransportState = C.GST_WEBRTC_SCTP_TRANSPORT_STATE_NEW        // new | ||||
| 	SCTP_TRANSPORT_STATE_CONNECTING SCTPTransportState = C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTING // connecting | ||||
| 	SCTP_TRANSPORT_STATE_CONNECTED  SCTPTransportState = C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTED  // connected | ||||
| 	SCTP_TRANSPORT_STATE_CLOSED     SCTPTransportState = C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CLOSED     // closed | ||||
| ) | ||||
|  | ||||
| func (e SCTPTransportState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_SCTP_TRANSPORT_STATE_NEW: | ||||
| 		return "new" | ||||
| 	case C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTING: | ||||
| 		return "connecting" | ||||
| 	case C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTED: | ||||
| 		return "connected" | ||||
| 	case C.GST_WEBRTC_SCTP_TRANSPORT_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type SDPType C.GstWebRTCSDPType | ||||
|  | ||||
| const ( | ||||
| 	SDP_TYPE_OFFER    SDPType = C.GST_WEBRTC_SDP_TYPE_OFFER    // offer | ||||
| 	SDP_TYPE_PRANSWER SDPType = C.GST_WEBRTC_SDP_TYPE_PRANSWER // pranswer | ||||
| 	SDP_TYPE_ANSWER   SDPType = C.GST_WEBRTC_SDP_TYPE_ANSWER   // answer | ||||
| 	SDP_TYPE_ROLLBACK SDPType = C.GST_WEBRTC_SDP_TYPE_ROLLBACK // rollback | ||||
| ) | ||||
|  | ||||
| func (e SDPType) String() string { | ||||
| 	// returned string is const gchar* and must not be freed | ||||
| 	cstring := C.gst_webrtc_sdp_type_to_string(C.GstWebRTCSDPType(e)) | ||||
|  | ||||
| 	return C.GoString(cstring) | ||||
| } | ||||
|  | ||||
| func SDPTypeFromString(s string) SDPType { | ||||
| 	switch s { | ||||
| 	case "offer": | ||||
| 		return SDP_TYPE_OFFER | ||||
| 	case "pranswer": | ||||
| 		return SDP_TYPE_PRANSWER | ||||
| 	case "answer": | ||||
| 		return SDP_TYPE_ANSWER | ||||
| 	case "rollback": | ||||
| 		return SDP_TYPE_ROLLBACK | ||||
| 	default: | ||||
| 		panic("Unknown SDPType") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type SignalingState C.GstWebRTCSignalingState | ||||
|  | ||||
| const ( | ||||
| 	SIGNALING_STATE_STABLE               SignalingState = C.GST_WEBRTC_SIGNALING_STATE_STABLE               // stable | ||||
| 	SIGNALING_STATE_CLOSED               SignalingState = C.GST_WEBRTC_SIGNALING_STATE_CLOSED               // closed | ||||
| 	SIGNALING_STATE_HAVE_LOCAL_OFFER     SignalingState = C.GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_OFFER     // have-local-offer | ||||
| 	SIGNALING_STATE_HAVE_REMOTE_OFFER    SignalingState = C.GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_OFFER    // have-remote-offer | ||||
| 	SIGNALING_STATE_HAVE_LOCAL_PRANSWER  SignalingState = C.GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_PRANSWER  // have-local-pranswer | ||||
| 	SIGNALING_STATE_HAVE_REMOTE_PRANSWER SignalingState = C.GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_PRANSWER // have-remote-pranswer | ||||
| ) | ||||
|  | ||||
| func (e SignalingState) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_STABLE: | ||||
| 		return "stable" | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_CLOSED: | ||||
| 		return "closed" | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_OFFER: | ||||
| 		return "have-local-offer" | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_OFFER: | ||||
| 		return "have-remote-offer" | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_PRANSWER: | ||||
| 		return "have-local-pranswer" | ||||
| 	case C.GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_PRANSWER: | ||||
| 		return "have-remote-pranswer" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| type StatsType C.GstWebRTCStatsType | ||||
|  | ||||
| const ( | ||||
| 	STATS_CODEC               StatsType = C.GST_WEBRTC_STATS_CODEC               // codec | ||||
| 	STATS_INBOUND_RTP         StatsType = C.GST_WEBRTC_STATS_INBOUND_RTP         // inbound-rtp | ||||
| 	STATS_OUTBOUND_RTP        StatsType = C.GST_WEBRTC_STATS_OUTBOUND_RTP        // outbound-rtp | ||||
| 	STATS_REMOTE_INBOUND_RTP  StatsType = C.GST_WEBRTC_STATS_REMOTE_INBOUND_RTP  // remote-inbound-rtp | ||||
| 	STATS_REMOTE_OUTBOUND_RTP StatsType = C.GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP // remote-outbound-rtp | ||||
| 	STATS_CSRC                StatsType = C.GST_WEBRTC_STATS_CSRC                // csrc | ||||
| 	STATS_PEER_CONNECTION     StatsType = C.GST_WEBRTC_STATS_PEER_CONNECTION     // peer-connection | ||||
| 	STATS_DATA_CHANNEL        StatsType = C.GST_WEBRTC_STATS_DATA_CHANNEL        // data-channel | ||||
| 	STATS_STREAM              StatsType = C.GST_WEBRTC_STATS_STREAM              // stream | ||||
| 	STATS_TRANSPORT           StatsType = C.GST_WEBRTC_STATS_TRANSPORT           // transport | ||||
| 	STATS_CANDIDATE_PAIR      StatsType = C.GST_WEBRTC_STATS_CANDIDATE_PAIR      // candidate-pair | ||||
| 	STATS_LOCAL_CANDIDATE     StatsType = C.GST_WEBRTC_STATS_LOCAL_CANDIDATE     // local-candidate | ||||
| 	STATS_REMOTE_CANDIDATE    StatsType = C.GST_WEBRTC_STATS_REMOTE_CANDIDATE    // remote-candidate | ||||
| 	STATS_CERTIFICATE         StatsType = C.GST_WEBRTC_STATS_CERTIFICATE         // certificate | ||||
| ) | ||||
|  | ||||
| func (e StatsType) String() string { | ||||
| 	switch e { | ||||
| 	case C.GST_WEBRTC_STATS_CODEC: | ||||
| 		return "codec" | ||||
| 	case C.GST_WEBRTC_STATS_INBOUND_RTP: | ||||
| 		return "inbound-rtp" | ||||
| 	case C.GST_WEBRTC_STATS_OUTBOUND_RTP: | ||||
| 		return "outbound-rtp" | ||||
| 	case C.GST_WEBRTC_STATS_REMOTE_INBOUND_RTP: | ||||
| 		return "remote-inbound-rtp" | ||||
| 	case C.GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP: | ||||
| 		return "remote-outbound-rtp" | ||||
| 	case C.GST_WEBRTC_STATS_CSRC: | ||||
| 		return "csrc" | ||||
| 	case C.GST_WEBRTC_STATS_PEER_CONNECTION: | ||||
| 		return "peer-connection" | ||||
| 	case C.GST_WEBRTC_STATS_DATA_CHANNEL: | ||||
| 		return "data-channel" | ||||
| 	case C.GST_WEBRTC_STATS_STREAM: | ||||
| 		return "stream" | ||||
| 	case C.GST_WEBRTC_STATS_TRANSPORT: | ||||
| 		return "transport" | ||||
| 	case C.GST_WEBRTC_STATS_CANDIDATE_PAIR: | ||||
| 		return "candidate-pair" | ||||
| 	case C.GST_WEBRTC_STATS_LOCAL_CANDIDATE: | ||||
| 		return "local-candidate" | ||||
| 	case C.GST_WEBRTC_STATS_REMOTE_CANDIDATE: | ||||
| 		return "remote-candidate" | ||||
| 	case C.GST_WEBRTC_STATS_CERTIFICATE: | ||||
| 		return "certificate" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
							
								
								
									
										8
									
								
								gst/gstwebrtc/gst.go.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								gst/gstwebrtc/gst.go.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef __GST_WEBRTC_GO_H__ | ||||
| #define __GST_WEBRTC_GO_H__ | ||||
|  | ||||
| #define GST_USE_UNSTABLE_API // webrtc is unstable | ||||
|  | ||||
| #include <gst/webrtc/webrtc.h> | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										7
									
								
								gst/gstwebrtc/pkg_config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								gst/gstwebrtc/pkg_config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| /* | ||||
| #cgo pkg-config: gstreamer-webrtc-1.0 | ||||
| #cgo CFLAGS: -Wno-deprecated-declarations -g -Wall | ||||
| */ | ||||
| import "C" | ||||
							
								
								
									
										45
									
								
								gst/gstwebrtc/rtp_transceiver.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								gst/gstwebrtc/rtp_transceiver.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| // #include "gst.go.h" | ||||
| import "C" | ||||
| import ( | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/go-gst/go-glib/glib" | ||||
| 	"github.com/go-gst/go-gst/gst" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
|  | ||||
| 	tm := []glib.TypeMarshaler{ | ||||
| 		{T: glib.Type(C.GST_TYPE_WEBRTC_RTP_TRANSCEIVER), F: marshalRTPTransceiver}, | ||||
| 	} | ||||
|  | ||||
| 	glib.RegisterGValueMarshalers(tm) | ||||
| } | ||||
|  | ||||
| type RTPTransceiver struct { | ||||
| 	*gst.Object | ||||
| } | ||||
|  | ||||
| // ToGValue implements glib.ValueTransformer | ||||
| func (tc *RTPTransceiver) ToGValue() (*glib.Value, error) { | ||||
| 	val, err := glib.ValueInit(glib.Type(C.GST_TYPE_WEBRTC_RTP_TRANSCEIVER)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	val.SetInstance(unsafe.Pointer(tc.Instance())) | ||||
| 	return val, nil | ||||
| } | ||||
|  | ||||
| func wrapRTPTransceiver(p unsafe.Pointer) *RTPTransceiver { | ||||
| 	return &RTPTransceiver{ | ||||
| 		Object: gst.FromGstObjectUnsafeNone(p), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func marshalRTPTransceiver(p unsafe.Pointer) (interface{}, error) { | ||||
| 	c := C.g_value_get_object((*C.GValue)(p)) | ||||
|  | ||||
| 	return wrapRTPTransceiver(unsafe.Pointer(c)), nil | ||||
| } | ||||
							
								
								
									
										9
									
								
								gst/gstwebrtc/rtp_transceiver_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								gst/gstwebrtc/rtp_transceiver_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package gstwebrtc_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestRTPTransceiverGValueMarshal(t *testing.T) { | ||||
| 	t.Skip("Not implemented, because we don't have a constructor for RTPTransceiver") | ||||
| } | ||||
							
								
								
									
										120
									
								
								gst/gstwebrtc/session_description.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								gst/gstwebrtc/session_description.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| package gstwebrtc | ||||
|  | ||||
| // #include "gst.go.h" | ||||
| import "C" | ||||
| import ( | ||||
| 	"runtime" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/go-gst/go-glib/glib" | ||||
| 	"github.com/go-gst/go-gst/gst/gstsdp" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
|  | ||||
| 	tm := []glib.TypeMarshaler{ | ||||
| 		{T: glib.Type(C.GST_TYPE_WEBRTC_SESSION_DESCRIPTION), F: marshalSessionDescription}, | ||||
| 	} | ||||
|  | ||||
| 	glib.RegisterGValueMarshalers(tm) | ||||
| } | ||||
|  | ||||
| type SessionDescription struct { | ||||
| 	ptr *C.GstWebRTCSessionDescription | ||||
| } | ||||
|  | ||||
| func NewSessionDescription(t SDPType, sdp *gstsdp.Message) *SessionDescription { | ||||
| 	sd := C.gst_webrtc_session_description_new( | ||||
| 		C.GstWebRTCSDPType(t), | ||||
| 		(*C.GstSDPMessage)(sdp.UnownedCopy().Instance()), | ||||
| 	) | ||||
|  | ||||
| 	return wrapSessionDescriptionAndFinalize(sd) | ||||
| } | ||||
|  | ||||
| func wrapSessionDescriptionAndFinalize(sdp *C.GstWebRTCSessionDescription) *SessionDescription { | ||||
| 	sd := &SessionDescription{ | ||||
| 		ptr: sdp, | ||||
| 	} | ||||
|  | ||||
| 	// this requires that we copy the SDP message before passing it to any transfer-ownership function | ||||
| 	runtime.SetFinalizer(sd, func(sd *SessionDescription) { | ||||
| 		sd.Free() | ||||
| 	}) | ||||
|  | ||||
| 	return sd | ||||
| } | ||||
|  | ||||
| // W3RTCSessionDescription is used to marshal/unmarshal SessionDescription to/from JSON. | ||||
| // | ||||
| // We cannot implement the json.(Un-)Marshaler interfaces on SessionDescription directly because | ||||
| // the finalizer would run and free the memory, because the value would have to be copied. | ||||
| // | ||||
| // it complies with the WebRTC spec for SessionDescription, see https://www.w3.org/TR/webrtc/#rtcsessiondescription-class | ||||
| type W3RTCSessionDescription struct { | ||||
| 	Type string `json:"type"` | ||||
| 	Sdp  string `json:"sdp"` | ||||
| } | ||||
|  | ||||
| // ToGstSDP converts a W3RTCSessionDescription to a SessionDescription | ||||
| func (w3SDP *W3RTCSessionDescription) ToGstSDP() (*SessionDescription, error) { | ||||
| 	sdp, err := gstsdp.ParseSDPMessage(w3SDP.Sdp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return NewSessionDescription(SDPTypeFromString(w3SDP.Type), sdp), nil | ||||
| } | ||||
|  | ||||
| // ToW3SDP returns a W3RTCSessionDescription that can be marshaled to JSON | ||||
| func (sd *SessionDescription) ToW3SDP() W3RTCSessionDescription { | ||||
| 	jsonSDP := W3RTCSessionDescription{ | ||||
| 		Type: SDPType(sd.ptr._type).String(), | ||||
| 		Sdp:  gstsdp.NewMessageFromUnsafe(unsafe.Pointer(sd.ptr.sdp)).String(), | ||||
| 	} | ||||
|  | ||||
| 	return jsonSDP | ||||
| } | ||||
|  | ||||
| func (sd *SessionDescription) Free() { | ||||
| 	C.gst_webrtc_session_description_free(sd.ptr) | ||||
| } | ||||
|  | ||||
| // UnownedCopy creates a new copy of the SessionDescription that will not be finalized | ||||
| // | ||||
| // this is needed for passing the SessionDescription to other functions that will take ownership of it. | ||||
| // | ||||
| // used in the bindings, should not be called by application code | ||||
| func (sd *SessionDescription) UnownedCopy() *SessionDescription { | ||||
| 	newSD := C.gst_webrtc_session_description_copy(sd.ptr) | ||||
|  | ||||
| 	return &SessionDescription{ | ||||
| 		ptr: newSD, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Copy creates a new copy of the SessionDescription | ||||
| func (sd *SessionDescription) Copy() *SessionDescription { | ||||
| 	return wrapSessionDescriptionAndFinalize(sd.UnownedCopy().ptr) | ||||
| } | ||||
|  | ||||
| // ToGValue implements glib.ValueTransformer | ||||
| func (sd *SessionDescription) ToGValue() (*glib.Value, error) { | ||||
| 	val, err := glib.ValueInit(glib.Type(C.GST_TYPE_WEBRTC_SESSION_DESCRIPTION)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	val.SetBoxed(unsafe.Pointer(sd.ptr)) | ||||
| 	return val, nil | ||||
| } | ||||
|  | ||||
| func marshalSessionDescription(p unsafe.Pointer) (interface{}, error) { | ||||
| 	c := C.g_value_get_boxed((*C.GValue)(p)) | ||||
|  | ||||
| 	// we don't own this memory, so we need to copy it to prevent other code from freeing it | ||||
| 	ref := &SessionDescription{ | ||||
| 		ptr: (*C.GstWebRTCSessionDescription)(c), | ||||
| 	} | ||||
|  | ||||
| 	return ref.Copy(), nil | ||||
| } | ||||
							
								
								
									
										58
									
								
								gst/gstwebrtc/session_description_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								gst/gstwebrtc/session_description_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| package gstwebrtc_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-gst/go-gst/gst/gstsdp" | ||||
| 	"github.com/go-gst/go-gst/gst/gstwebrtc" | ||||
| ) | ||||
|  | ||||
| func TestSessionDescriptionGValueMarshal(t *testing.T) { | ||||
| 	sdp, err := gstsdp.ParseSDPMessage("v=0\nm=audio 4000 RTP/AVP 111\na=rtpmap:111 OPUS/48000/2\nm=video 4000 RTP/AVP 96\na=rtpmap:96 VP8/90000\na=my-sdp-value") | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	sd := gstwebrtc.NewSessionDescription(gstwebrtc.SDP_TYPE_OFFER, sdp) | ||||
|  | ||||
| 	gv, err := sd.ToGValue() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	sdI, err := gv.GoValue() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	sd, ok := sdI.(*gstwebrtc.SessionDescription) | ||||
|  | ||||
| 	if !ok { | ||||
| 		t.Fatal("Failed to convert to SessionDescription") | ||||
| 	} | ||||
|  | ||||
| 	_ = sd | ||||
| } | ||||
|  | ||||
| func TestSessionDescriptionJSONMarshal(t *testing.T) { | ||||
| 	sdp, err := gstsdp.ParseSDPMessage("v=0\nm=audio 4000 RTP/AVP 111\na=rtpmap:111 OPUS/48000/2\nm=video 4000 RTP/AVP 96\na=rtpmap:96 VP8/90000\na=my-sdp-value") | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	sd := gstwebrtc.NewSessionDescription(gstwebrtc.SDP_TYPE_OFFER, sdp) | ||||
|  | ||||
| 	w3 := sd.ToW3SDP() | ||||
|  | ||||
| 	sd, err = w3.ToGstSDP() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	_ = sd | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Wilhelm Bartel
					Wilhelm Bartel