install go2rtc on bob
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package webrtc
|
||||
|
||||
import (
|
||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
func (c *Conn) SetOffer(offer string) (err error) {
|
||||
c.offer = offer
|
||||
|
||||
sd := &sdp.SessionDescription{}
|
||||
if err = sd.Unmarshal([]byte(offer)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create transceivers with opposite direction
|
||||
for _, md := range sd.MediaDescriptions {
|
||||
var mid string
|
||||
var tr *webrtc.RTPTransceiver
|
||||
for _, attr := range md.Attributes {
|
||||
switch attr.Key {
|
||||
case core.DirectionSendRecv:
|
||||
tr, _ = c.pc.AddTransceiverFromTrack(NewTrack(md.MediaName.Media))
|
||||
case core.DirectionSendonly:
|
||||
tr, _ = c.pc.AddTransceiverFromKind(
|
||||
webrtc.NewRTPCodecType(md.MediaName.Media),
|
||||
webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionRecvonly},
|
||||
)
|
||||
case core.DirectionRecvonly:
|
||||
tr, _ = c.pc.AddTransceiverFromTrack(
|
||||
NewTrack(md.MediaName.Media),
|
||||
webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionSendonly},
|
||||
)
|
||||
case "mid":
|
||||
mid = attr.Value
|
||||
}
|
||||
}
|
||||
|
||||
if mid != "" && tr != nil {
|
||||
_ = tr.SetMid(mid)
|
||||
}
|
||||
}
|
||||
|
||||
c.Medias = UnmarshalMedias(sd.MediaDescriptions)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Conn) GetAnswer() (answer string, err error) {
|
||||
// we need to process remote offer after we create transeivers
|
||||
desc := webrtc.SessionDescription{Type: webrtc.SDPTypeOffer, SDP: c.offer}
|
||||
if err = c.pc.SetRemoteDescription(desc); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// disable transceivers if we don't have track, make direction=inactive
|
||||
transeivers:
|
||||
for _, tr := range c.pc.GetTransceivers() {
|
||||
for _, sender := range c.Senders {
|
||||
if sender.Media.ID == tr.Mid() {
|
||||
continue transeivers
|
||||
}
|
||||
}
|
||||
|
||||
switch tr.Direction() {
|
||||
case webrtc.RTPTransceiverDirectionSendrecv:
|
||||
_ = tr.Sender().Stop() // don't know if necessary
|
||||
_ = tr.SetSender(tr.Sender(), nil) // set direction to recvonly
|
||||
case webrtc.RTPTransceiverDirectionSendonly:
|
||||
_ = tr.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
if desc, err = c.pc.CreateAnswer(nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = c.pc.SetLocalDescription(desc); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return c.pc.LocalDescription().SDP, nil
|
||||
}
|
||||
|
||||
// GetCompleteAnswer - get SDP answer with candidates inside
|
||||
func (c *Conn) GetCompleteAnswer(candidates []string, filter func(*webrtc.ICECandidate) bool) (string, error) {
|
||||
var done = make(chan struct{})
|
||||
|
||||
c.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||
if candidate != nil {
|
||||
if filter == nil || filter(candidate) {
|
||||
candidates = append(candidates, candidate.ToJSON().Candidate)
|
||||
}
|
||||
} else {
|
||||
done <- struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
answer, err := c.GetAnswer()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
<-done
|
||||
|
||||
sd := &sdp.SessionDescription{}
|
||||
if err = sd.Unmarshal([]byte(answer)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
md := sd.MediaDescriptions[0]
|
||||
|
||||
for _, candidate := range candidates {
|
||||
md.WithPropertyAttribute(candidate)
|
||||
}
|
||||
|
||||
b, err := sd.Marshal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
Reference in New Issue
Block a user