mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
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:
86
internal/capture/buckets.go
Normal file
86
internal/capture/buckets.go
Normal 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
|
||||
}
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user