package webrtcconnection import ( "git.sense-t.eu.org/ACE/ace/servers/qemuserver" "github.com/pion/mediadevices" "github.com/pion/mediadevices/pkg/codec/opus" "github.com/pion/mediadevices/pkg/codec/x264" "github.com/pion/mediadevices/pkg/driver" "github.com/pion/mediadevices/pkg/prop" "github.com/pion/webrtc/v3" "github.com/sirupsen/logrus" ) const DefaultStreamID = "ace-server" type Connection struct { option *Options api *webrtc.API stream mediadevices.MediaStream QEMU *qemuserver.Server } func New(o *Options) (*Connection, error) { connection := &Connection{ option: o, } codecSelector, err := setupCodec(o.Video.BPS) if err != nil { return nil, err } me := &webrtc.MediaEngine{} codecSelector.Populate(me) connection.api = webrtc.NewAPI(webrtc.WithMediaEngine(me)) 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("------") } s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{ Video: func(mtc *mediadevices.MediaTrackConstraints) { mtc.Height = prop.Int(o.Video.Height) mtc.Width = prop.Int(o.Video.Width) }, 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) { logrus.Debug("received offer ", offer) rtc, err := c.api.NewPeerConnection(webrtc.Configuration{ 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() } }) for _, track := range c.stream.GetTracks() { track.OnEnded(func(err error) { logrus.Errorf("Track (ID: %s, kind: %s) ended with error: %v", track.ID(), track.Kind().String(), err) }) _, err := rtc.AddTransceiverFromTrack(track, webrtc.RTPTransceiverInit{ Direction: webrtc.RTPTransceiverDirectionSendonly, }) if err != nil { logrus.Error(err) } } rtc.OnDataChannel(c.dataChannel) 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 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 } codecSelector := mediadevices.NewCodecSelector( mediadevices.WithAudioEncoders(&opusParam), mediadevices.WithVideoEncoders(&x264Prarm), ) return codecSelector, nil }