Stream bucket manager (#12)

* refactor webrtc.

* bind track with a single connection.

* audio+video codec.

* move stream selection to bucket manager.

* audio w/o bucket manager.

* revert peer changes.

* return video IDs.

* destroy & recreate all.

* add video ID change.

* Track -> Recevier.
This commit is contained in:
Miroslav Šedivý
2022-10-17 13:39:31 +02:00
committed by GitHub
parent 095f9fe8ee
commit 5ad5daa6bb
11 changed files with 438 additions and 356 deletions

View File

@ -0,0 +1,86 @@
package capture
import (
"errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/types/codec"
)
type BucketsManagerCtx struct {
logger zerolog.Logger
codec codec.RTPCodec
streams map[string]*StreamSinkManagerCtx
streamIDs []string
}
func bucketsNew(codec codec.RTPCodec, streams map[string]*StreamSinkManagerCtx, streamIDs []string) *BucketsManagerCtx {
logger := log.With().
Str("module", "capture").
Str("submodule", "buckets").
Logger()
return &BucketsManagerCtx{
logger: logger,
codec: codec,
streams: streams,
streamIDs: streamIDs,
}
}
func (m *BucketsManagerCtx) shutdown() {
m.logger.Info().Msgf("shutdown")
}
func (m *BucketsManagerCtx) destroyAll() {
for _, video := range m.streams {
if video.Started() {
video.destroyPipeline()
}
}
}
func (m *BucketsManagerCtx) recreateAll() error {
for _, video := range m.streams {
if video.Started() {
err := video.createPipeline()
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
return err
}
}
}
return nil
}
func (m *BucketsManagerCtx) IDs() []string {
return m.streamIDs
}
func (m *BucketsManagerCtx) Codec() codec.RTPCodec {
return m.codec
}
func (m *BucketsManagerCtx) SetReceiver(receiver types.Receiver) error {
receiver.OnVideoIdChange(func(videoID string) error {
videoStream, ok := m.streams[videoID]
if !ok {
return types.ErrWebRTCVideoNotFound
}
return receiver.SetStream(videoStream)
})
// TODO: Save receiver.
return nil
}
func (m *BucketsManagerCtx) RemoveReceiver(receiver types.Receiver) error {
// TODO: Unsubribe from OnVideoIdChange.
// TODO: Remove receiver.
receiver.RemoveStream()
return nil
}

View File

@ -21,8 +21,7 @@ type CaptureManagerCtx struct {
broadcast *BroacastManagerCtx
screencast *ScreencastManagerCtx
audio *StreamSinkManagerCtx
videos map[string]*StreamSinkManagerCtx
videoIDs []string
video *BucketsManagerCtx
// sources
webcam *StreamSrcManagerCtx
@ -118,6 +117,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
"! appsink name=appsink", config.Display, config.ScreencastRate, config.ScreencastQuality,
)
}()),
audio: streamSinkNew(config.AudioCodec, func() (string, error) {
if config.AudioPipeline != "" {
// replace {device} with valid device
@ -133,8 +133,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
"! appsink name=appsink", config.AudioDevice, config.AudioCodec.Pipeline,
), nil
}, "audio"),
videos: videos,
videoIDs: config.VideoIDs,
video: bucketsNew(config.VideoCodec, videos, config.VideoIDs),
// sources
webcam: streamSrcNew(config.WebcamEnabled, map[string]string{
@ -195,11 +194,7 @@ func (manager *CaptureManagerCtx) Start() {
}
manager.desktop.OnBeforeScreenSizeChange(func() {
for _, video := range manager.videos {
if video.Started() {
video.destroyPipeline()
}
}
manager.video.destroyAll()
if manager.broadcast.Started() {
manager.broadcast.destroyPipeline()
@ -211,13 +206,9 @@ func (manager *CaptureManagerCtx) Start() {
})
manager.desktop.OnAfterScreenSizeChange(func() {
for _, video := range manager.videos {
if video.Started() {
err := video.createPipeline()
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
manager.logger.Panic().Err(err).Msg("unable to recreate video pipeline")
}
}
err := manager.video.recreateAll()
if err != nil {
manager.logger.Panic().Err(err).Msg("unable to recreate video pipelines")
}
if manager.broadcast.Started() {
@ -243,10 +234,7 @@ func (manager *CaptureManagerCtx) Shutdown() error {
manager.screencast.shutdown()
manager.audio.shutdown()
for _, video := range manager.videos {
video.shutdown()
}
manager.video.shutdown()
manager.webcam.shutdown()
manager.microphone.shutdown()
@ -266,13 +254,8 @@ func (manager *CaptureManagerCtx) Audio() types.StreamSinkManager {
return manager.audio
}
func (manager *CaptureManagerCtx) Video(videoID string) (types.StreamSinkManager, bool) {
video, ok := manager.videos[videoID]
return video, ok
}
func (manager *CaptureManagerCtx) VideoIDs() []string {
return manager.videoIDs
func (manager *CaptureManagerCtx) Video() types.BucketsManager {
return manager.video
}
func (manager *CaptureManagerCtx) Webcam() types.StreamSrcManager {