mirror of
https://github.com/go-gst/go-gst.git
synced 2025-09-27 04:15:56 +08:00
157 lines
3.0 KiB
Go
157 lines
3.0 KiB
Go
package gstsdp
|
|
|
|
// #include "gst.go.h"
|
|
import "C"
|
|
import (
|
|
"errors"
|
|
"iter"
|
|
"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
|
|
}
|
|
|
|
// NewMessage creates a new empty SDP message
|
|
func NewMessage() (*Message, error) {
|
|
var msg *C.GstSDPMessage
|
|
|
|
res := SDPResult(C.gst_sdp_message_new(&msg))
|
|
|
|
if res != SDPResultOk || msg == nil {
|
|
return nil, ErrSDPInvalid
|
|
}
|
|
|
|
return wrapSDPMessageAndFinalize(msg), nil
|
|
}
|
|
|
|
// 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.native())
|
|
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 {
|
|
if msg == nil {
|
|
return nil
|
|
}
|
|
|
|
var newMsg *C.GstSDPMessage
|
|
res := C.gst_sdp_message_copy(msg.native(), &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() {
|
|
if msg == nil || msg.ptr == nil {
|
|
return
|
|
}
|
|
C.gst_sdp_message_free(msg.ptr)
|
|
msg.ptr = nil
|
|
}
|
|
|
|
func (msg *Message) native() *C.GstSDPMessage {
|
|
if msg == nil {
|
|
return nil
|
|
}
|
|
|
|
return msg.ptr
|
|
}
|
|
|
|
func (msg *Message) Instance() unsafe.Pointer {
|
|
return unsafe.Pointer(msg.native())
|
|
}
|
|
|
|
func (msg *Message) MediasLen() int {
|
|
return int(C.gst_sdp_message_medias_len(msg.native()))
|
|
}
|
|
|
|
func (msg *Message) Media(i int) *Media {
|
|
cmedia := C.gst_sdp_message_get_media(msg.native(), C.uint(i))
|
|
|
|
if cmedia == nil {
|
|
return nil
|
|
}
|
|
|
|
media := &Media{
|
|
ptr: cmedia,
|
|
}
|
|
|
|
// keep the Message alive while we are handling the media
|
|
runtime.SetFinalizer(media, func(_ *Media) {
|
|
runtime.KeepAlive(msg)
|
|
})
|
|
|
|
return media
|
|
}
|
|
|
|
func (msg *Message) Medias() iter.Seq2[int, *Media] {
|
|
return func(yield func(int, *Media) bool) {
|
|
for i := 0; i < msg.MediasLen(); i++ {
|
|
if !yield(i, msg.Media(i)) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|