playback composition object

This commit is contained in:
Dmitry Sergeev
2026-09-01 00:43:57 +03:00
parent 03ebe5bbd0
commit 19e2e076e9
3 changed files with 170 additions and 1 deletions
+127
View File
@@ -0,0 +1,127 @@
package main
import (
"log"
mxladapter "mxl-player/internal/adapter/mxl"
"mxl-player/internal/output"
"mxl-player/internal/playback"
)
type playerPlayback struct {
Controller *playback.SessionController
Commands chan playback.SessionCommand
Video *playback.VideoBridge
Status *playback.StatusStore
Audio *output.SDLAudioSink
}
func newPlayerPlayback(
audioDevice uint32,
retry playback.RetryPolicy,
) (*playerPlayback, error) {
videoBridge := playback.NewVideoBridge()
statusStore := playback.NewStatusStore()
audioSink := output.NewSDLAudioSink(audioDevice)
observe := func(status playback.Status) {
statusStore.Observe(status)
if status.Err != nil {
log.Printf(
"%s: state=%v attempt=%d failed=%d: %v",
status.Unit,
status.State,
status.Attempt,
status.FailedAttempts,
status.Err,
)
return
}
log.Printf(
"%s: state=%v attempt=%d failed=%d",
status.Unit,
status.State,
status.Attempt,
status.FailedAttempts,
)
}
videoWorker, err := playback.NewVideoWorker(
mxladapter.VideoFactory{},
videoBridge,
retry,
mxladapter.ShouldRetry,
observe,
)
if err != nil {
_ = audioSink.Close()
return nil, err
}
videoSlot, err := playback.NewVideoSlot(videoWorker)
if err != nil {
_ = audioSink.Close()
return nil, err
}
audioWorker, err := playback.NewAudioWorker(
mxladapter.AudioFactory{},
audioSink,
retry,
mxladapter.ShouldRetry,
observe,
)
if err != nil {
_ = audioSink.Close()
return nil, err
}
audioSlot, err := playback.NewAudioSlot(audioWorker)
if err != nil {
_ = audioSink.Close()
return nil, err
}
syncWorker, err := playback.NewSyncWorker(
mxladapter.SyncFactory{},
videoBridge,
audioSink,
retry,
mxladapter.ShouldRetry,
observe,
)
if err != nil {
_ = audioSink.Close()
return nil, err
}
syncSlot, err := playback.NewSyncSlot(syncWorker)
if err != nil {
_ = audioSink.Close()
return nil, err
}
controller, err := playback.NewSessionController(
videoSlot,
audioSlot,
syncSlot,
func(video, audio playback.FeedConfig) bool {
return video.Domain == audio.Domain
},
)
if err != nil {
_ = audioSink.Close()
return nil, err
}
return &playerPlayback{
Controller: controller,
Commands: make(chan playback.SessionCommand, 32),
Video: videoBridge,
Status: statusStore,
Audio: audioSink,
}, nil
}
func (p *playerPlayback) Close() error {
return p.Audio.Close()
}