Skip to content

Commit 09990c8

Browse files
committed
[streamplayer] Make min jitter buffer configurable
1 parent a825d19 commit 09990c8

5 files changed

Lines changed: 63 additions & 38 deletions

File tree

pkg/streamd/grpc/goconv/stream_player.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ func StreamPlaybackConfigGo2GRPC(
3636
cfg *sptypes.Config,
3737
) *streamd_grpc.StreamPlaybackConfig {
3838
return &streamd_grpc.StreamPlaybackConfig{
39-
JitterBufDurationSecs: cfg.JitterBufDuration.Seconds(),
39+
JitterBufDurationSecs: cfg.JitterBufMaxDuration.Seconds(),
4040
CatchupMaxSpeedFactor: cfg.CatchupMaxSpeedFactor,
41-
MaxCatchupAtLagSecs: cfg.MaxCatchupAtLag.Seconds(),
41+
MaxCatchupAtLagSecs: cfg.CatchupAtMaxLag.Seconds(),
4242
StartTimeoutSecs: cfg.StartTimeout.Seconds(),
4343
ReadTimeoutSecs: cfg.ReadTimeout.Seconds(),
4444
OverriddenURL: cfg.OverrideURL,
@@ -51,9 +51,9 @@ func StreamPlaybackConfigGRPC2Go(
5151
cfg *streamd_grpc.StreamPlaybackConfig,
5252
) sptypes.Config {
5353
return sptypes.Config{
54-
JitterBufDuration: secsGRPC2Go(cfg.JitterBufDurationSecs),
54+
JitterBufMaxDuration: secsGRPC2Go(cfg.JitterBufDurationSecs),
5555
CatchupMaxSpeedFactor: cfg.CatchupMaxSpeedFactor,
56-
MaxCatchupAtLag: secsGRPC2Go(cfg.MaxCatchupAtLagSecs),
56+
CatchupAtMaxLag: secsGRPC2Go(cfg.MaxCatchupAtLagSecs),
5757
StartTimeout: secsGRPC2Go(cfg.StartTimeoutSecs),
5858
ReadTimeout: secsGRPC2Go(cfg.ReadTimeoutSecs),
5959
OverrideURL: cfg.GetOverriddenURL(),

pkg/streampanel/restream.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -772,30 +772,43 @@ func (p *Panel) openAddOrEditPlayerWindow(
772772
}
773773
overrideURL.OnChanged(overrideURL.Text)
774774

775-
jitterBufDuration := xfyne.NewNumericalEntry()
776-
jitterBufDuration.SetPlaceHolder("amount of seconds")
777-
jitterBufDuration.SetText(fmt.Sprintf("%v", cfg.JitterBufDuration.Seconds()))
778-
jitterBufDuration.OnChanged = func(s string) {
775+
jitterBufMinDuration := xfyne.NewNumericalEntry()
776+
jitterBufMinDuration.SetPlaceHolder("amount of seconds")
777+
jitterBufMinDuration.SetText(fmt.Sprintf("%v", cfg.JitterBufMinDuration.Seconds()))
778+
jitterBufMinDuration.OnChanged = func(s string) {
779779
f, err := strconv.ParseFloat(s, 64)
780780
if err != nil {
781781
p.DisplayError(fmt.Errorf("unable to parse '%s' as float: %w", s, err))
782782
return
783783
}
784784

785-
cfg.JitterBufDuration = time.Duration(f * float64(time.Second))
785+
cfg.JitterBufMinDuration = time.Duration(f * float64(time.Second))
786+
}
787+
788+
jitterBufMaxDuration := xfyne.NewNumericalEntry()
789+
jitterBufMaxDuration.SetPlaceHolder("amount of seconds")
790+
jitterBufMaxDuration.SetText(fmt.Sprintf("%v", cfg.JitterBufMaxDuration.Seconds()))
791+
jitterBufMaxDuration.OnChanged = func(s string) {
792+
f, err := strconv.ParseFloat(s, 64)
793+
if err != nil {
794+
p.DisplayError(fmt.Errorf("unable to parse '%s' as float: %w", s, err))
795+
return
796+
}
797+
798+
cfg.JitterBufMaxDuration = time.Duration(f * float64(time.Second))
786799
}
787800

788801
maxCatchupAtLag := xfyne.NewNumericalEntry()
789802
maxCatchupAtLag.SetPlaceHolder("amount of seconds")
790-
maxCatchupAtLag.SetText(fmt.Sprintf("%v", cfg.MaxCatchupAtLag.Seconds()))
803+
maxCatchupAtLag.SetText(fmt.Sprintf("%v", cfg.CatchupAtMaxLag.Seconds()))
791804
maxCatchupAtLag.OnChanged = func(s string) {
792805
f, err := strconv.ParseFloat(s, 64)
793806
if err != nil {
794807
p.DisplayError(fmt.Errorf("unable to parse '%s' as float: %w", s, err))
795808
return
796809
}
797810

798-
cfg.MaxCatchupAtLag = time.Duration(f * float64(time.Second))
811+
cfg.CatchupAtMaxLag = time.Duration(f * float64(time.Second))
799812
}
800813

801814
startTimeout := xfyne.NewNumericalEntry()
@@ -876,8 +889,10 @@ func (p *Panel) openAddOrEditPlayerWindow(
876889
startTimeout,
877890
widget.NewLabel("Read timeout (seconds):"),
878891
readTimeout,
879-
widget.NewLabel("Jitter buffer size (seconds):"),
880-
jitterBufDuration,
892+
widget.NewLabel("Jitter buffer min size (seconds):"),
893+
jitterBufMinDuration,
894+
widget.NewLabel("Jitter buffer max size (seconds):"),
895+
jitterBufMaxDuration,
881896
widget.NewLabel("Maximal catchup speed (float):"),
882897
catchupMaxSpeedFactor,
883898
widget.NewLabel("Maximal catchup at lab (seconds):"),

pkg/streamplayer/cmd/streamplayer/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,20 +153,20 @@ func main() {
153153

154154
jitterBufDuration := xfyne.NewNumericalEntry()
155155
jitterBufDuration.SetPlaceHolder("amount of seconds")
156-
jitterBufDuration.SetText(fmt.Sprintf("%f", defaultCfg.JitterBufDuration.Seconds()))
156+
jitterBufDuration.SetText(fmt.Sprintf("%f", defaultCfg.JitterBufMaxDuration.Seconds()))
157157
jitterBufDuration.OnSubmitted = func(s string) {
158158
f, err := strconv.ParseFloat(s, 64)
159159
if err != nil {
160160
errorMessage.SetText(fmt.Sprintf("unable to parse '%s' as float: %s", s, err))
161161
return
162162
}
163163

164-
p.Resetup(types.OptionJitterBufDuration(time.Duration(f * float64(time.Second))))
164+
p.Resetup(types.OptionJitterBufMaxDuration(time.Duration(f * float64(time.Second))))
165165
}
166166

167167
maxCatchupAtLag := xfyne.NewNumericalEntry()
168168
maxCatchupAtLag.SetPlaceHolder("amount of seconds")
169-
maxCatchupAtLag.SetText(fmt.Sprintf("%f", defaultCfg.MaxCatchupAtLag.Seconds()))
169+
maxCatchupAtLag.SetText(fmt.Sprintf("%f", defaultCfg.CatchupAtMaxLag.Seconds()))
170170
maxCatchupAtLag.OnSubmitted = func(s string) {
171171
f, err := strconv.ParseFloat(s, 64)
172172
if err != nil {

pkg/streamplayer/stream_player.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ const (
3434
enableSlowDown = true
3535
minSpeed = 0.975
3636
minSpeedDifference = 0.01
37-
minJitterBufDuration = 500 * time.Millisecond
3837
jitterBufDecayHalftime = 5 * time.Minute
3938
playerCheckInterval = 100 * time.Millisecond
4039
)
@@ -145,11 +144,11 @@ func (sp *StreamPlayers) Create(
145144
)
146145
}
147146

148-
if p.Config.MaxCatchupAtLag <= p.Config.JitterBufDuration {
147+
if p.Config.CatchupAtMaxLag <= p.Config.JitterBufMaxDuration {
149148
return nil, fmt.Errorf(
150149
"MaxCatchupAtLag (%v) should be higher than JitterBufDuration (%v)",
151-
p.Config.MaxCatchupAtLag,
152-
p.Config.JitterBufDuration,
150+
p.Config.CatchupAtMaxLag,
151+
p.Config.JitterBufMaxDuration,
153152
)
154153
}
155154

@@ -680,7 +679,7 @@ func (p *StreamPlayerHandler) controllerLoop(
680679
if err != nil {
681680
err = fmt.Errorf("unable to get length: %w", err)
682681
}
683-
if l > p.Config.JitterBufDuration/2 {
682+
if l > p.Config.JitterBufMaxDuration/2 {
684683
if err := player.Seek(ctx, -time.Second, true, true); err != nil {
685684
logger.Errorf(ctx, "unable to seek: %v", err)
686685
}
@@ -802,7 +801,7 @@ func (p *StreamPlayerHandler) controllerLoop(
802801
}
803802
p.CurrentJitterBufDuration = min(
804803
p.CurrentJitterBufDuration+jitterBufDurationIncrease,
805-
p.Config.JitterBufDuration,
804+
p.Config.JitterBufMaxDuration,
806805
)
807806
logger.Debugf(ctx,
808807
"StreamPlayer[%s].controllerLoop: increased jitter buffer duration to %v (increased by %v)",
@@ -988,7 +987,7 @@ func (p *StreamPlayerHandler) controllerLoop(
988987
jitterBufFactor := math.Exp(math.Log(2) / (jitterBufDecayHalftime.Seconds() / playerCheckInterval.Seconds()))
989988
p.CurrentJitterBufDuration = max(
990989
time.Duration(float64(p.CurrentJitterBufDuration)*jitterBufFactor),
991-
minJitterBufDuration,
990+
p.Config.JitterBufMinDuration,
992991
)
993992
logger.Tracef(ctx,
994993
"StreamPlayer[%s].controllerLoop: increasing jitter buffer duration factor: %v (halftime: %v, interval: %v); new duration: %v",
@@ -1002,7 +1001,7 @@ func (p *StreamPlayerHandler) controllerLoop(
10021001
wantSpeed := float64(1) +
10031002
(p.Config.CatchupMaxSpeedFactor-float64(1))*
10041003
(lag-p.CurrentJitterBufDuration).Seconds()/
1005-
(p.Config.MaxCatchupAtLag-p.CurrentJitterBufDuration).Seconds()
1004+
(p.Config.CatchupAtMaxLag-p.CurrentJitterBufDuration).Seconds()
10061005

10071006
setSpeed := p.WantSpeedAverage.Update(wantSpeed)
10081007
setSpeed = float64(uint(setSpeed*50)) / 50 // to avoid flickering (for example between 1.0001 and 1.0000)
@@ -1015,7 +1014,7 @@ func (p *StreamPlayerHandler) controllerLoop(
10151014
p.Config.CatchupMaxSpeedFactor,
10161015
lag.Seconds(),
10171016
p.CurrentJitterBufDuration.Seconds(),
1018-
p.Config.MaxCatchupAtLag.Seconds(),
1017+
p.Config.CatchupAtMaxLag.Seconds(),
10191018
p.CurrentJitterBufDuration.Seconds(),
10201019
l, pos,
10211020
)

pkg/streamplayer/types/config.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ type FuncNotifyStart func(ctx context.Context, streamID streamtypes.StreamID)
1212
type GetRestartChanFunc func() <-chan struct{}
1313

1414
type Config struct {
15-
JitterBufDuration time.Duration
15+
JitterBufMaxDuration time.Duration
16+
JitterBufMinDuration time.Duration
1617
CatchupMaxSpeedFactor float64
17-
MaxCatchupAtLag time.Duration
18+
CatchupAtMaxLag time.Duration
1819
StartTimeout time.Duration
1920
ReadTimeout time.Duration
2021
NotifierStart []FuncNotifyStart `yaml:"-"`
@@ -27,14 +28,17 @@ type Config struct {
2728

2829
func (cfg Config) Options() Options {
2930
var opts Options
30-
if cfg.JitterBufDuration != 0 {
31-
opts = append(opts, OptionJitterBufDuration(cfg.JitterBufDuration))
31+
if cfg.JitterBufMaxDuration != 0 {
32+
opts = append(opts, OptionJitterBufMaxDuration(cfg.JitterBufMaxDuration))
33+
}
34+
if cfg.JitterBufMinDuration != 0 {
35+
opts = append(opts, OptionJitterBufMinDuration(cfg.JitterBufMinDuration))
3236
}
3337
if cfg.CatchupMaxSpeedFactor != 0 {
3438
opts = append(opts, OptionCatchupMaxSpeedFactor(cfg.CatchupMaxSpeedFactor))
3539
}
36-
if cfg.MaxCatchupAtLag != 0 {
37-
opts = append(opts, OptionMaxCatchupAtLag(cfg.MaxCatchupAtLag))
40+
if cfg.CatchupAtMaxLag != 0 {
41+
opts = append(opts, OptionMaxCatchupAtLag(cfg.CatchupAtMaxLag))
3842
}
3943
if cfg.StartTimeout != 0 {
4044
opts = append(opts, OptionStartTimeout(cfg.StartTimeout))
@@ -83,18 +87,25 @@ func (s Options) apply(cfg *Config) {
8387

8488
var DefaultConfig = func(ctx context.Context) Config {
8589
return Config{
86-
JitterBufDuration: 3 * time.Second,
87-
CatchupMaxSpeedFactor: 10,
88-
MaxCatchupAtLag: 21 * time.Second,
90+
JitterBufMinDuration: 200 * time.Millisecond,
91+
JitterBufMaxDuration: 3 * time.Minute,
92+
CatchupMaxSpeedFactor: 1.1,
93+
CatchupAtMaxLag: 3 * time.Minute,
8994
StartTimeout: 10 * time.Second,
9095
ReadTimeout: 10 * time.Second,
9196
}
9297
}
9398

94-
type OptionJitterBufDuration time.Duration
99+
type OptionJitterBufMaxDuration time.Duration
100+
101+
func (s OptionJitterBufMaxDuration) Apply(cfg *Config) {
102+
cfg.JitterBufMaxDuration = time.Duration(s)
103+
}
104+
105+
type OptionJitterBufMinDuration time.Duration
95106

96-
func (s OptionJitterBufDuration) Apply(cfg *Config) {
97-
cfg.JitterBufDuration = time.Duration(s)
107+
func (s OptionJitterBufMinDuration) Apply(cfg *Config) {
108+
cfg.JitterBufMinDuration = time.Duration(s)
98109
}
99110

100111
type OptionCatchupMaxSpeedFactor float64
@@ -106,7 +117,7 @@ func (s OptionCatchupMaxSpeedFactor) Apply(cfg *Config) {
106117
type OptionMaxCatchupAtLag time.Duration
107118

108119
func (s OptionMaxCatchupAtLag) Apply(cfg *Config) {
109-
cfg.MaxCatchupAtLag = time.Duration(s)
120+
cfg.CatchupAtMaxLag = time.Duration(s)
110121
}
111122

112123
type OptionStartTimeout time.Duration

0 commit comments

Comments
 (0)