2022-09-26 03:04:07 +00:00
|
|
|
package webrtcconnection
|
|
|
|
|
|
|
|
import (
|
2022-09-27 02:21:06 +00:00
|
|
|
"git.sense-t.eu.org/ACE/ace/servers/qemuserver"
|
2022-09-26 03:04:07 +00:00
|
|
|
"github.com/pion/mediadevices"
|
|
|
|
"github.com/pion/mediadevices/pkg/codec/opus"
|
|
|
|
"github.com/pion/mediadevices/pkg/codec/x264"
|
2022-09-27 02:21:06 +00:00
|
|
|
"github.com/pion/mediadevices/pkg/driver"
|
2022-09-27 06:36:25 +00:00
|
|
|
"github.com/pion/mediadevices/pkg/prop"
|
2022-09-26 03:04:07 +00:00
|
|
|
"github.com/pion/webrtc/v3"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
const DefaultStreamID = "ace-server"
|
|
|
|
|
|
|
|
type Connection struct {
|
|
|
|
option *Options
|
2022-09-26 08:07:25 +00:00
|
|
|
api *webrtc.API
|
|
|
|
stream mediadevices.MediaStream
|
2022-09-27 02:21:06 +00:00
|
|
|
QEMU *qemuserver.Server
|
2022-09-26 03:04:07 +00:00
|
|
|
}
|
|
|
|
|
2022-09-26 08:07:25 +00:00
|
|
|
func New(o *Options) (*Connection, error) {
|
|
|
|
connection := &Connection{
|
2022-09-26 03:04:07 +00:00
|
|
|
option: o,
|
|
|
|
}
|
2022-09-26 08:07:25 +00:00
|
|
|
codecSelector, err := setupCodec(o.Video.BPS, o.Audio.BPS)
|
2022-09-26 03:04:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
me := &webrtc.MediaEngine{}
|
|
|
|
codecSelector.Populate(me)
|
|
|
|
|
2022-09-26 08:07:25 +00:00
|
|
|
connection.api = webrtc.NewAPI(webrtc.WithMediaEngine(me))
|
|
|
|
|
2022-09-27 02:21:06 +00:00
|
|
|
logrus.Debug("list devices:")
|
|
|
|
logrus.Debug("------")
|
|
|
|
devices := driver.GetManager().Query(func(d driver.Driver) bool { return true })
|
|
|
|
for _, device := range devices {
|
|
|
|
logrus.Debug(device.ID())
|
|
|
|
logrus.Debug(device.Info())
|
|
|
|
logrus.Debug(device.Properties())
|
|
|
|
logrus.Debug(device.Status())
|
|
|
|
logrus.Debug("------")
|
|
|
|
}
|
|
|
|
|
2022-09-26 08:07:25 +00:00
|
|
|
s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
|
2022-09-27 06:36:25 +00:00
|
|
|
Video: func(mtc *mediadevices.MediaTrackConstraints) {
|
|
|
|
mtc.Height = prop.Int(o.Video.Height)
|
|
|
|
mtc.Width = prop.Int(o.Video.Width)
|
|
|
|
},
|
2022-09-26 08:07:25 +00:00
|
|
|
Audio: func(mtc *mediadevices.MediaTrackConstraints) {},
|
|
|
|
Codec: codecSelector,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
connection.stream = s
|
|
|
|
|
|
|
|
return connection, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Connection) Regist(offer *webrtc.SessionDescription) (*webrtc.SessionDescription, error) {
|
2022-09-27 02:21:06 +00:00
|
|
|
logrus.Debug("received offer ", offer)
|
2022-09-26 08:07:25 +00:00
|
|
|
|
|
|
|
rtc, err := c.api.NewPeerConnection(webrtc.Configuration{
|
2022-09-26 03:04:07 +00:00
|
|
|
ICEServers: []webrtc.ICEServer{
|
|
|
|
{
|
|
|
|
URLs: c.option.STUNServers,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
rtc.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
|
|
|
|
logrus.Debug("connection state has changed: ", connectionState.String())
|
|
|
|
|
|
|
|
switch connectionState {
|
|
|
|
case webrtc.ICEConnectionStateFailed:
|
|
|
|
fallthrough
|
|
|
|
case webrtc.ICEConnectionStateClosed:
|
|
|
|
rtc.Close()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2022-09-26 08:07:25 +00:00
|
|
|
for _, track := range c.stream.GetTracks() {
|
2022-09-26 03:04:07 +00:00
|
|
|
track.OnEnded(func(err error) {
|
2022-09-27 06:36:25 +00:00
|
|
|
logrus.Errorf("Track (ID: %s, kind: %s) ended with error: %v", track.ID(), track.Kind().String(), err)
|
2022-09-26 03:04:07 +00:00
|
|
|
})
|
|
|
|
_, err := rtc.AddTransceiverFromTrack(track, webrtc.RTPTransceiverInit{
|
|
|
|
Direction: webrtc.RTPTransceiverDirectionSendonly,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
logrus.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 02:21:06 +00:00
|
|
|
rtc.OnDataChannel(c.dataChannel)
|
2022-09-26 03:04:07 +00:00
|
|
|
|
|
|
|
if err := rtc.SetRemoteDescription(*offer); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debug("offer set")
|
|
|
|
|
|
|
|
answer, err := rtc.CreateAnswer(nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
gatherComplete := webrtc.GatheringCompletePromise(rtc)
|
|
|
|
|
|
|
|
if err := rtc.SetLocalDescription(answer); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debug("answer set")
|
|
|
|
|
|
|
|
<-gatherComplete
|
|
|
|
|
|
|
|
defer logrus.Debug("regist complete")
|
|
|
|
return rtc.LocalDescription(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupCodec(videoBPS, audioBPS int) (*mediadevices.CodecSelector, error) {
|
|
|
|
x264Prarm, err := x264.NewParams()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
x264Prarm.BitRate = videoBPS
|
|
|
|
|
|
|
|
opusParam, err := opus.NewParams()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
opusParam.BitRate = audioBPS
|
|
|
|
|
|
|
|
codecSelector := mediadevices.NewCodecSelector(
|
|
|
|
mediadevices.WithAudioEncoders(&opusParam),
|
|
|
|
mediadevices.WithVideoEncoders(&x264Prarm),
|
|
|
|
)
|
|
|
|
return codecSelector, nil
|
|
|
|
}
|