Switch to listeners for webrtc pause (#31)

* switch to listeners for webrtc pause.

* group track vars.

* do not set or remove stream when paused.
This commit is contained in:
Miroslav Šedivý 2023-02-20 19:48:04 +01:00 committed by GitHub
parent 0086900053
commit 30200d4057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 13 deletions

View File

@ -163,9 +163,12 @@ func (manager *StreamSinkManagerCtx) stop() {
func (manager *StreamSinkManagerCtx) addListener(listener *func(sample types.Sample)) { func (manager *StreamSinkManagerCtx) addListener(listener *func(sample types.Sample)) {
ptr := reflect.ValueOf(listener).Pointer() ptr := reflect.ValueOf(listener).Pointer()
emitKeyframe := false
manager.listenersMu.Lock() manager.listenersMu.Lock()
if manager.waitForKf { if manager.waitForKf {
// if this is the first listener, we need to emit a keyframe
emitKeyframe = len(manager.listenersKf) == 0
// if we're waiting for a keyframe, add it to the keyframe lobby // if we're waiting for a keyframe, add it to the keyframe lobby
manager.listenersKf[ptr] = listener manager.listenersKf[ptr] = listener
} else { } else {
@ -178,7 +181,7 @@ func (manager *StreamSinkManagerCtx) addListener(listener *func(sample types.Sam
manager.currentListeners.Set(float64(manager.ListenersCount())) manager.currentListeners.Set(float64(manager.ListenersCount()))
// if we will be waiting for a keyframe, emit one now // if we will be waiting for a keyframe, emit one now
if manager.pipeline != nil && manager.waitForKf { if manager.pipeline != nil && emitKeyframe {
manager.pipeline.EmitVideoKeyframe() manager.pipeline.EmitVideoKeyframe()
} }
} }

View File

@ -18,11 +18,12 @@ import (
type Track struct { type Track struct {
logger zerolog.Logger logger zerolog.Logger
track *webrtc.TrackLocalStaticSample track *webrtc.TrackLocalStaticSample
paused bool
videoAuto bool
videoAutoMu sync.RWMutex
listener func(sample types.Sample) listener func(sample types.Sample)
videoAuto bool
videoAutoMu sync.RWMutex
paused bool
stream types.StreamSinkManager stream types.StreamSinkManager
streamMu sync.Mutex streamMu sync.Mutex
@ -60,10 +61,6 @@ func NewTrack(logger zerolog.Logger, codec codec.RTPCodec, connection *webrtc.Pe
} }
t.listener = func(sample types.Sample) { t.listener = func(sample types.Sample) {
if t.paused {
return
}
err := track.WriteSample(media.Sample{ err := track.WriteSample(media.Sample{
Data: sample.Data, Data: sample.Data,
Duration: sample.Duration, Duration: sample.Duration,
@ -112,6 +109,12 @@ func (t *Track) SetStream(stream types.StreamSinkManager) (bool, error) {
return false, nil return false, nil
} }
// if paused, we switch the stream but don't add the listener
if t.paused {
t.stream = stream
return true, nil
}
var err error var err error
if t.stream != nil { if t.stream != nil {
err = t.stream.MoveListenerTo(&t.listener, stream) err = t.stream.MoveListenerTo(&t.listener, stream)
@ -123,7 +126,6 @@ func (t *Track) SetStream(stream types.StreamSinkManager) (bool, error) {
} }
t.stream = stream t.stream = stream
return true, nil return true, nil
} }
@ -131,13 +133,39 @@ func (t *Track) RemoveStream() {
t.streamMu.Lock() t.streamMu.Lock()
defer t.streamMu.Unlock() defer t.streamMu.Unlock()
if t.stream != nil { // if there is no stream, or paused, do nothing
_ = t.stream.RemoveListener(&t.listener) if t.stream == nil || t.paused {
t.stream = nil return
} }
err := t.stream.RemoveListener(&t.listener)
if err != nil {
t.logger.Warn().Err(err).Msg("failed to remove listener from stream")
}
t.stream = nil
} }
func (t *Track) SetPaused(paused bool) { func (t *Track) SetPaused(paused bool) {
t.streamMu.Lock()
defer t.streamMu.Unlock()
// if there is no state change or no stream, do nothing
if t.paused == paused || t.stream == nil {
return
}
var err error
if paused {
err = t.stream.RemoveListener(&t.listener)
} else {
err = t.stream.AddListener(&t.listener)
}
if err != nil {
t.logger.Warn().Err(err).Msg("failed to change listener state")
return
}
t.paused = paused t.paused = paused
} }