mirror of
				https://github.com/go-gst/go-gst.git
				synced 2025-10-31 19:42:33 +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/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 | 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 h1:XTGhwk2BWYjW/UZ08y7ojf3iPPRiYtXL0W6vJkXNKFc= | ||||||
| github.com/go-gst/go-glib v1.1.0/go.mod h1:JybIYeoHNwCkHGaBf1fHNIaM4sQTrJPkPLsi7dmPNOU= | 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 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= | ||||||
| github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= | ||||||
| golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= | 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 | 		done: nil, // cannot be awaited if received from FFI | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	prom.Ref() | ||||||
|  |  | ||||||
|  | 	runtime.SetFinalizer(prom, func(p *Promise) { | ||||||
|  | 		p.Unref() | ||||||
|  | 	}) | ||||||
|  |  | ||||||
| 	return prom, nil | 	return prom, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,10 +4,8 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| 	"sync" |  | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 	"unsafe" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| //go:noinline | //go:noinline | ||||||
| @@ -35,9 +33,7 @@ func awaitGC() { | |||||||
| } | } | ||||||
|  |  | ||||||
| func TestPromise(t *testing.T) { | func TestPromise(t *testing.T) { | ||||||
| 	initOnce.Do(func() { | 	Init(nil) | ||||||
| 		Init(nil) |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	prom := NewPromise() | 	prom := NewPromise() | ||||||
| 	cprom := prom.Instance() | 	cprom := prom.Instance() | ||||||
| @@ -87,12 +83,8 @@ func TestPromise(t *testing.T) { | |||||||
| 	awaitGC() | 	awaitGC() | ||||||
| } | } | ||||||
|  |  | ||||||
| var initOnce sync.Once |  | ||||||
|  |  | ||||||
| func TestPromiseMarshal(t *testing.T) { | func TestPromiseMarshal(t *testing.T) { | ||||||
| 	initOnce.Do(func() { | 	Init(nil) | ||||||
| 		Init(nil) |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	prom := NewPromise() | 	prom := NewPromise() | ||||||
|  |  | ||||||
| @@ -102,7 +94,7 @@ func TestPromiseMarshal(t *testing.T) { | |||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	receivedPromI, err := marshalPromise(unsafe.Pointer(gv.GValue)) | 	receivedPromI, err := gv.GoValue() | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		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