replace video track on demand.

This commit is contained in:
Miroslav Šedivý 2021-02-05 20:35:30 +01:00
parent c81bca9b2f
commit 6756114e30
6 changed files with 42 additions and 23 deletions

View File

@ -11,6 +11,7 @@ const (
SIGNAL_ANSWER = "signal/answer" SIGNAL_ANSWER = "signal/answer"
SIGNAL_PROVIDE = "signal/provide" SIGNAL_PROVIDE = "signal/provide"
SIGNAL_CANDIDATE = "signal/candidate" SIGNAL_CANDIDATE = "signal/candidate"
SIGNAL_VIDEO = "signal/video"
) )
const ( const (

View File

@ -57,6 +57,11 @@ type SignalAnswer struct {
SDP string `json:"sdp"` SDP string `json:"sdp"`
} }
type SignalVideo struct {
Event string `json:"event,omitempty"`
VideoID string `json:"video_id"`
}
///////////////////////////// /////////////////////////////
// Member // Member
///////////////////////////// /////////////////////////////

View File

@ -57,6 +57,8 @@ func (manager *WebRTCManagerCtx) Start() {
videoIDs := manager.capture.VideoIDs() videoIDs := manager.capture.VideoIDs()
manager.videoTracks = map[string]*webrtc.TrackLocalStaticSample{} manager.videoTracks = map[string]*webrtc.TrackLocalStaticSample{}
for _, videoID := range videoIDs { for _, videoID := range videoIDs {
videoID := videoID
video, ok := manager.capture.Video(videoID) video, ok := manager.capture.Video(videoID)
if !ok { if !ok {
manager.logger.Warn().Str("videoID", videoID).Msg("video stream not found, skipping") manager.logger.Warn().Str("videoID", videoID).Msg("video stream not found, skipping")
@ -65,12 +67,12 @@ func (manager *WebRTCManagerCtx) Start() {
track, err := webrtc.NewTrackLocalStaticSample(video.Codec().Capability, "video", "stream") track, err := webrtc.NewTrackLocalStaticSample(video.Codec().Capability, "video", "stream")
if err != nil { if err != nil {
manager.logger.Panic().Err(err).Msgf("unable to create video (%s) track", videoID) manager.logger.Panic().Err(err).Str("videoID", videoID).Msg("unable to create video track")
} }
video.OnSample(func(sample types.Sample) { video.OnSample(func(sample types.Sample) {
if err := track.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe { if err := track.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe {
manager.logger.Warn().Err(err).Msgf("video (%s) pipeline failed to write", videoID) manager.logger.Warn().Err(err).Str("videoID", videoID).Msg("vide pipeline failed to write")
} }
}) })
@ -141,16 +143,12 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.Sess
}) })
} }
_, err = connection.AddTransceiverFromTrack(manager.audioTrack, webrtc.RtpTransceiverInit{ _, err = connection.AddTrack(manager.audioTrack)
Direction: webrtc.RTPTransceiverDirectionSendonly,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
videoTransceiver, err := connection.AddTransceiverFromTrack(manager.videoTracks[manager.defaultVideoID], webrtc.RtpTransceiverInit{ videoSender, err := connection.AddTrack(manager.videoTracks[manager.defaultVideoID])
Direction: webrtc.RTPTransceiverDirectionSendonly,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -206,13 +204,13 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.Sess
}) })
session.SetWebRTCPeer(&WebRTCPeerCtx{ session.SetWebRTCPeer(&WebRTCPeerCtx{
api: api, api: api,
engine: engine, engine: engine,
settings: settings, settings: settings,
connection: connection, connection: connection,
configuration: configuration, configuration: configuration,
videoTracks: manager.videoTracks, videoTracks: manager.videoTracks,
videoTransceiver: videoTransceiver, videoSender: videoSender,
}) })
return connection.LocalDescription(), nil return connection.LocalDescription(), nil

View File

@ -7,13 +7,13 @@ import (
) )
type WebRTCPeerCtx struct { type WebRTCPeerCtx struct {
api *webrtc.API api *webrtc.API
engine *webrtc.MediaEngine engine *webrtc.MediaEngine
settings *webrtc.SettingEngine settings *webrtc.SettingEngine
connection *webrtc.PeerConnection connection *webrtc.PeerConnection
configuration *webrtc.Configuration configuration *webrtc.Configuration
videoTracks map[string]*webrtc.TrackLocalStaticSample videoTracks map[string]*webrtc.TrackLocalStaticSample
videoTransceiver *webrtc.RTPTransceiver videoSender *webrtc.RTPSender
} }
func (webrtc_peer *WebRTCPeerCtx) SignalAnswer(sdp string) error { func (webrtc_peer *WebRTCPeerCtx) SignalAnswer(sdp string) error {
@ -33,7 +33,7 @@ func (webrtc_peer *WebRTCPeerCtx) SetVideoID(videoID string) error {
return fmt.Errorf("videoID not found in available tracks") return fmt.Errorf("videoID not found in available tracks")
} }
return webrtc_peer.videoTransceiver.Sender().ReplaceTrack(track) return webrtc_peer.videoSender.ReplaceTrack(track)
} }
func (webrtc_peer *WebRTCPeerCtx) Destroy() error { func (webrtc_peer *WebRTCPeerCtx) Destroy() error {

View File

@ -59,6 +59,11 @@ func (h *MessageHandlerCtx) Message(session types.Session, raw []byte) bool {
err = utils.Unmarshal(payload, raw, func() error { err = utils.Unmarshal(payload, raw, func() error {
return h.signalCandidate(session, payload) return h.signalCandidate(session, payload)
}) })
case event.SIGNAL_VIDEO:
payload := &message.SignalVideo{}
err = utils.Unmarshal(payload, raw, func() error {
return h.signalVideo(session, payload)
})
// Control Events // Control Events
case event.CONTROL_RELEASE: case event.CONTROL_RELEASE:

View File

@ -44,3 +44,13 @@ func (h *MessageHandlerCtx) signalCandidate(session types.Session, payload *mess
return peer.SignalCandidate(*payload.ICECandidateInit) return peer.SignalCandidate(*payload.ICECandidateInit)
} }
func (h *MessageHandlerCtx) signalVideo(session types.Session, payload *message.SignalVideo) error {
peer := session.GetWebRTCPeer()
if peer == nil {
h.logger.Debug().Msg("webRTC peer does not exist")
return nil
}
return peer.SetVideoID(payload.VideoID)
}