132 lines
3.5 KiB
Go
132 lines
3.5 KiB
Go
package localserver
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sync/atomic"
|
|
|
|
"github.com/pion/webrtc/v3"
|
|
)
|
|
|
|
const (
|
|
VIDEO = "video"
|
|
STOP_VIDEO = "stop_video"
|
|
)
|
|
|
|
type WebrtcCallVideoManager struct{}
|
|
|
|
func NewWebrtcCallVideoManager() *WebrtcCallVideoManager {
|
|
return new(WebrtcCallVideoManager)
|
|
}
|
|
|
|
func (w *WebrtcCallVideoManager) HandleCallEvent(from string, squadId string, eventId string, payload map[string]interface{}, data []byte, manager *WebRTCCallManager) (err error) {
|
|
done, errCh := make(chan struct{}), make(chan error)
|
|
go func() {
|
|
logger.Println("got an event in call video manager", from, eventId, payload)
|
|
switch eventId {
|
|
case VIDEO:
|
|
if e := w.video(from, squadId, manager); e != nil {
|
|
errCh <- e
|
|
return
|
|
}
|
|
case STOP_VIDEO:
|
|
if e := w.stopVideo(from, squadId, manager); e != nil {
|
|
errCh <- e
|
|
return
|
|
}
|
|
}
|
|
done <- struct{}{}
|
|
}()
|
|
select {
|
|
case <-done:
|
|
return nil
|
|
case err = <-errCh:
|
|
return
|
|
}
|
|
}
|
|
|
|
func (w *WebrtcCallVideoManager) video(peerId string, squadId string, manager *WebRTCCallManager) (err error) {
|
|
if _, ok := manager.Squads[squadId]; !ok {
|
|
err = fmt.Errorf("no correponding squad found")
|
|
return
|
|
}
|
|
logger.Println("sending video event", peerId)
|
|
manager.RemoteTracksMux.RLock()
|
|
for _, v := range manager.RemoteTracks[peerId] {
|
|
if v.Track.Kind() == webrtc.RTPCodecTypeVideo {
|
|
atomic.SwapInt32(v.rdv, 0)
|
|
}
|
|
}
|
|
manager.RemoteTracksMux.RUnlock()
|
|
manager.SquadMapMux.Lock()
|
|
defer manager.SquadMapMux.Unlock()
|
|
for _, member := range manager.Squads[squadId].Members {
|
|
manager.DataChannelMapMux.Lock()
|
|
if _, ok := manager.DataChannels[member]; ok && member != peerId {
|
|
bs, marshalErr := json.Marshal(map[string]interface{}{
|
|
"type": VIDEO,
|
|
"from": peerId,
|
|
"payload": map[string]interface{}{},
|
|
})
|
|
if marshalErr != nil {
|
|
logger.Println(err)
|
|
manager.DataChannelMapMux.Unlock()
|
|
continue
|
|
}
|
|
if sendErr := atomicallyExecute(manager.DataChannels[member].l, func() (err error) {
|
|
err = manager.DataChannels[member].DataChannel.SendText(string(bs))
|
|
return
|
|
}); sendErr != nil {
|
|
logger.Println(sendErr)
|
|
}
|
|
}
|
|
manager.DataChannelMapMux.Unlock()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (w *WebrtcCallVideoManager) stopVideo(peerId string, squadId string, manager *WebRTCCallManager) (err error) {
|
|
if _, ok := manager.Squads[squadId]; !ok {
|
|
err = fmt.Errorf("no correponding squad found")
|
|
return
|
|
}
|
|
logger.Println("sending stop video event", peerId)
|
|
manager.RemoteTracksMux.RLock()
|
|
for _, v := range manager.RemoteTracks[peerId] {
|
|
if v.Track.Kind() == webrtc.RTPCodecTypeVideo {
|
|
atomic.SwapInt32(v.rdv, 1)
|
|
}
|
|
}
|
|
manager.RemoteTracksMux.RUnlock()
|
|
manager.SquadMapMux.Lock()
|
|
defer manager.SquadMapMux.Unlock()
|
|
for _, member := range manager.Squads[squadId].Members {
|
|
manager.DataChannelMapMux.Lock()
|
|
if _, ok := manager.DataChannels[member]; ok && member != peerId {
|
|
bs, marshalErr := json.Marshal(map[string]interface{}{
|
|
"type": STOP_VIDEO,
|
|
"from": peerId,
|
|
"payload": map[string]interface{}{},
|
|
})
|
|
if marshalErr != nil {
|
|
logger.Println(err)
|
|
manager.DataChannelMapMux.Unlock()
|
|
continue
|
|
}
|
|
for {
|
|
if atomic.CompareAndSwapUint32(manager.DataChannels[member].l, 0, 1) {
|
|
defer atomic.SwapUint32(manager.DataChannels[member].l, 0)
|
|
if sendErr := manager.DataChannels[member].DataChannel.SendText(string(bs)); sendErr != nil {
|
|
logger.Println(sendErr)
|
|
}
|
|
break
|
|
} else {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
manager.DataChannelMapMux.Unlock()
|
|
}
|
|
return
|
|
}
|