Skip to content

Commit 1430f89

Browse files
committed
Add rebuffering avoidance to the demo page
1 parent 23de3e7 commit 1430f89

4 files changed

Lines changed: 185 additions & 0 deletions

File tree

demo/scripts/components/Options/BufferOptions.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ const DEFAULT_MAX_BUFFER_AHEAD = DEFAULT_VALUES.player.maxBufferAhead;
99
const DEFAULT_MAX_BUFFER_BEHIND = DEFAULT_VALUES.player.maxBufferBehind;
1010
const DEFAULT_MAX_VIDEO_BUFFER_SIZE = DEFAULT_VALUES.player.maxVideoBufferSize;
1111
const DEFAULT_WANTED_BUFFER_AHEAD = DEFAULT_VALUES.player.wantedBufferAhead;
12+
const DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE =
13+
DEFAULT_VALUES.loadVideo.experimentalOptions
14+
.playbackRateBasedRebufferingAvoidanceSettings.onBufferGapSize;
15+
const DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE =
16+
DEFAULT_VALUES.loadVideo.experimentalOptions
17+
.playbackRateBasedRebufferingAvoidanceSettings.minPlaybackRate;
1218

1319
/**
1420
* @param {Object} props
@@ -19,19 +25,27 @@ function BufferOptions({
1925
maxVideoBufferSize,
2026
maxBufferAhead,
2127
maxBufferBehind,
28+
rebufferingAvoidanceBufferGapSize,
29+
rebufferingAvoidanceMinPlaybackRate,
2230
onWantedBufferAheadChange,
2331
onMaxVideoBufferSizeChange,
2432
onMaxBufferAheadChange,
2533
onMaxBufferBehindChange,
34+
onRebufferingAvoidanceBufferGapSizeChange,
35+
onRebufferingAvoidanceMinPlaybackRateChange,
2636
}: {
2737
wantedBufferAhead: number;
2838
maxVideoBufferSize: number;
2939
maxBufferAhead: number;
3040
maxBufferBehind: number;
41+
rebufferingAvoidanceBufferGapSize: number;
42+
rebufferingAvoidanceMinPlaybackRate: number;
3143
onWantedBufferAheadChange: (newVal: number) => void;
3244
onMaxVideoBufferSizeChange: (newVal: number) => void;
3345
onMaxBufferBehindChange: (newVal: number) => void;
3446
onMaxBufferAheadChange: (newVal: number) => void;
47+
onRebufferingAvoidanceBufferGapSizeChange: (newVal: number) => void;
48+
onRebufferingAvoidanceMinPlaybackRateChange: (newVal: number) => void;
3549
}): React.JSX.Element {
3650
/* Value of the `wantedBufferAhead` input */
3751
const [wantedBufferAheadStr, setWantedBufferAheadStr] = useState(
@@ -45,6 +59,14 @@ function BufferOptions({
4559
const [maxBufferBehindStr, setMaxBufferBehindStr] = useState(String(maxBufferBehind));
4660
/* Value of the `maxBufferAhead` input */
4761
const [maxBufferAheadStr, setMaxBufferAheadStr] = useState(String(maxBufferAhead));
62+
/* Value of the `rebufferingAvoidanceBufferGapSize` input */
63+
const [rebufferingAvoidanceBufferGapSizeStr, setRebufferingAvoidanceBufferGapSizeStr] =
64+
useState(String(rebufferingAvoidanceBufferGapSize));
65+
/* Value of the `rebufferingAvoidanceMinPlaybackRate` input */
66+
const [
67+
rebufferingAvoidanceMinPlaybackRateStr,
68+
setRebufferingAvoidanceMinPlaybackRateStr,
69+
] = useState(String(rebufferingAvoidanceMinPlaybackRate));
4870
/*
4971
* Keep track of the "limit maxBufferAhead" toggle:
5072
* `false` == checkbox enabled
@@ -66,6 +88,7 @@ function BufferOptions({
6688
const [isMaxVideoBufferSizeLimited, setMaxVideoBufferSizeLimit] = useState(
6789
maxVideoBufferSize !== Infinity,
6890
);
91+
const isRebufferingAvoidanceEnabled = rebufferingAvoidanceBufferGapSize !== 0;
6992

7093
// Update `wantedBufferAhead` when its linked text change
7194
useEffect(() => {
@@ -98,6 +121,26 @@ function BufferOptions({
98121
onMaxBufferBehindChange(newVal);
99122
}, [maxBufferBehindStr]);
100123

124+
// Update `rebufferingAvoidanceBufferGapSize` when its linked text change
125+
useEffect(() => {
126+
// Note that this unnecessarily also run on first render - there seem to be
127+
// no quick and easy way to disable this in react.
128+
// This is not too problematic so I put up with it.
129+
let newVal = parseFloat(rebufferingAvoidanceBufferGapSizeStr);
130+
newVal = isNaN(newVal) ? DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE : newVal;
131+
onRebufferingAvoidanceBufferGapSizeChange(newVal);
132+
}, [rebufferingAvoidanceBufferGapSizeStr]);
133+
134+
// Update `rebufferingAvoidanceMinPlaybackRate` when its linked text change
135+
useEffect(() => {
136+
// Note that this unnecessarily also run on first render - there seem to be
137+
// no quick and easy way to disable this in react.
138+
// This is not too problematic so I put up with it.
139+
let newVal = parseFloat(rebufferingAvoidanceMinPlaybackRateStr);
140+
newVal = isNaN(newVal) ? DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE : newVal;
141+
onRebufferingAvoidanceMinPlaybackRateChange(newVal);
142+
}, [rebufferingAvoidanceMinPlaybackRateStr]);
143+
101144
const onChangeLimitMaxBufferAhead = useCallback((isNotLimited: boolean) => {
102145
if (isNotLimited) {
103146
setMaxBufferAheadLimit(false);
@@ -128,6 +171,14 @@ function BufferOptions({
128171
}
129172
}, []);
130173

174+
const onRebufferingAvoidanceEnableClick = useCallback((isEnabled: boolean) => {
175+
if (isEnabled) {
176+
setRebufferingAvoidanceBufferGapSizeStr("0");
177+
} else {
178+
setRebufferingAvoidanceBufferGapSizeStr("1.5");
179+
}
180+
}, []);
181+
131182
const onWantedBufferAheadResetClick = React.useCallback(() => {
132183
setWantedBufferAheadStr(String(DEFAULT_WANTED_BUFFER_AHEAD));
133184
}, []);
@@ -147,6 +198,18 @@ function BufferOptions({
147198
setMaxBufferBehindLimit(DEFAULT_MAX_BUFFER_BEHIND !== Infinity);
148199
}, []);
149200

201+
const onRebufferingAvoidanceBufferGapSizeResetClick = React.useCallback(() => {
202+
setRebufferingAvoidanceBufferGapSizeStr(
203+
String(DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE),
204+
);
205+
}, []);
206+
207+
const onRebufferingAvoidanceMinPlaybackRateResetClick = React.useCallback(() => {
208+
setRebufferingAvoidanceMinPlaybackRateStr(
209+
String(DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE),
210+
);
211+
}, []);
212+
150213
return (
151214
<Fragment>
152215
<li>
@@ -242,6 +305,47 @@ function BufferOptions({
242305
: `Manually cleaning data ${maxBufferBehind} second(s) behind the current position`}
243306
</span>
244307
</li>
308+
<li>
309+
<PlayerOptionNumberInput
310+
ariaLabel="Playback Rate Based Rebuffering Avoidance Buffer Size option"
311+
label="playbackRateBasedRebufferingAvoidanceBufferSize"
312+
title="Rebuffering Avoidance: Buffer Size"
313+
valueAsString={rebufferingAvoidanceBufferGapSizeStr}
314+
defaultValueAsNumber={DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE}
315+
isDisabled={!isRebufferingAvoidanceEnabled}
316+
onUpdateValue={setRebufferingAvoidanceBufferGapSizeStr}
317+
onResetClick={onRebufferingAvoidanceBufferGapSizeResetClick}
318+
/>
319+
<Checkbox
320+
className="playerOptionsCheckBox"
321+
ariaLabel="Do not enable Playback Rate-Based Rebuffering Avoidance"
322+
name="rebufferingAvoidanceEnable"
323+
checked={!isRebufferingAvoidanceEnabled}
324+
onChange={onRebufferingAvoidanceEnableClick}
325+
>
326+
Disable
327+
</Checkbox>
328+
<span className="option-desc">
329+
{rebufferingAvoidanceBufferGapSize <= 0 || !isRebufferingAvoidanceEnabled
330+
? "No triggering Playback-Rate-based rebuffering Avoidance"
331+
: `Starting rebuffering avoidance strategy once ${rebufferingAvoidanceBufferGapSize} second(s) is left in the buffer`}
332+
</span>
333+
<PlayerOptionNumberInput
334+
ariaLabel="Playback Rate Based Rebuffering Avoidance Min Playback Rate option"
335+
label="playbackRateBasedRebufferingAvoidanceMinPlaybackRate"
336+
title="Rebuffering Avoidance: Playback Rate"
337+
valueAsString={rebufferingAvoidanceMinPlaybackRateStr}
338+
defaultValueAsNumber={DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE}
339+
isDisabled={!isRebufferingAvoidanceEnabled}
340+
onUpdateValue={setRebufferingAvoidanceMinPlaybackRateStr}
341+
onResetClick={onRebufferingAvoidanceMinPlaybackRateResetClick}
342+
/>
343+
<span className="option-desc">
344+
{rebufferingAvoidanceBufferGapSize <= 0 || !isRebufferingAvoidanceEnabled
345+
? "No triggering Playback-Rate-based rebuffering Avoidance"
346+
: `Rebuffering avoidance strategies will play at ${rebufferingAvoidanceMinPlaybackRate}x the speed once ${rebufferingAvoidanceBufferGapSize} second(s) is left in the buffer`}
347+
</span>
348+
</li>
245349
</Fragment>
246350
);
247351
}

demo/scripts/controllers/Settings.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ function Settings({
7575
onCodecSwitch,
7676
onAudioTracksNotPlayable,
7777
onVideoTracksNotPlayable,
78+
experimentalOptions,
7879
} = loadVideoOptions;
7980
const cmcdCommunicationMethod = cmcd?.communicationType ?? "disabled";
8081
const { manifest: manifestRequestConfig, segment: segmentRequestConfig } =
@@ -350,6 +351,58 @@ function Settings({
350351
[playerOptions],
351352
);
352353

354+
const onRebufferingAvoidanceBufferGapSizeChange = useCallback(
355+
(rebufferingAvoidanceBufferGapSize: number) => {
356+
updateLoadVideoOptions((prevOptions) => {
357+
if (
358+
rebufferingAvoidanceBufferGapSize ===
359+
prevOptions.experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
360+
.onBufferGapSize
361+
) {
362+
return prevOptions;
363+
}
364+
return Object.assign({}, prevOptions, {
365+
...prevOptions.experimentalOptions,
366+
experimentalOptions: {
367+
playbackRateBasedRebufferingAvoidanceSettings: {
368+
onBufferGapSize: rebufferingAvoidanceBufferGapSize,
369+
minPlaybackRate:
370+
prevOptions.experimentalOptions
371+
.playbackRateBasedRebufferingAvoidanceSettings.minPlaybackRate,
372+
},
373+
},
374+
});
375+
});
376+
},
377+
[playerOptions],
378+
);
379+
380+
const onRebufferingAvoidanceMinPlaybackRateChange = useCallback(
381+
(rebufferingAvoidanceMinPlaybackRate: number) => {
382+
updateLoadVideoOptions((prevOptions) => {
383+
if (
384+
rebufferingAvoidanceMinPlaybackRate ===
385+
prevOptions.experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
386+
.minPlaybackRate
387+
) {
388+
return prevOptions;
389+
}
390+
return Object.assign({}, prevOptions, {
391+
experimentalOptions: {
392+
...prevOptions.experimentalOptions,
393+
playbackRateBasedRebufferingAvoidanceSettings: {
394+
onBufferGapSize:
395+
prevOptions.experimentalOptions
396+
.playbackRateBasedRebufferingAvoidanceSettings.onBufferGapSize,
397+
minPlaybackRate: rebufferingAvoidanceMinPlaybackRate,
398+
},
399+
},
400+
});
401+
});
402+
},
403+
[playerOptions],
404+
);
405+
353406
const onMaxVideoBufferSizeChange = useCallback(
354407
(maxVideoBufferSize: number) => {
355408
updatePlayerOptions((prevOptions) => {
@@ -475,10 +528,24 @@ function Settings({
475528
maxVideoBufferSize={maxVideoBufferSize}
476529
maxBufferAhead={maxBufferAhead}
477530
maxBufferBehind={maxBufferBehind}
531+
rebufferingAvoidanceBufferGapSize={
532+
experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
533+
.onBufferGapSize
534+
}
535+
rebufferingAvoidanceMinPlaybackRate={
536+
experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
537+
.minPlaybackRate
538+
}
478539
onWantedBufferAheadChange={onWantedBufferAheadChange}
479540
onMaxBufferAheadChange={onMaxBufferAheadChange}
480541
onMaxBufferBehindChange={onMaxBufferBehindChange}
481542
onMaxVideoBufferSizeChange={onMaxVideoBufferSizeChange}
543+
onRebufferingAvoidanceBufferGapSizeChange={
544+
onRebufferingAvoidanceBufferGapSizeChange
545+
}
546+
onRebufferingAvoidanceMinPlaybackRateChange={
547+
onRebufferingAvoidanceMinPlaybackRateChange
548+
}
482549
/>
483550
</Option>
484551
</div>

demo/scripts/lib/defaultOptionsValues.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
ICmcdOptions,
33
IConstructorOptions,
44
ILoadVideoOptions,
5+
IPlaybackRateBasedRebufferingAvoidanceSettings,
56
} from "../../../src/public_types";
67

78
const defaultOptionsValues = {
@@ -33,6 +34,13 @@ const defaultOptionsValues = {
3334
onCodecSwitch: "continue",
3435
onAudioTracksNotPlayable: "error",
3536
onVideoTracksNotPlayable: "error",
37+
experimentalOptions: {
38+
enableRepresentationAvoidance: true,
39+
playbackRateBasedRebufferingAvoidanceSettings: {
40+
onBufferGapSize: 0,
41+
minPlaybackRate: 0.95,
42+
} as IPlaybackRateBasedRebufferingAvoidanceSettings,
43+
},
3644
},
3745
} satisfies {
3846
player: IConstructorOptions;

demo/scripts/modules/player/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ const PlayerModule = declareModule(
303303
textTrackElement,
304304
onAudioTracksNotPlayable: state.get("onAudioTracksNotPlayable"),
305305
onVideoTracksNotPlayable: state.get("onVideoTracksNotPlayable"),
306+
experimentalOptions: {
307+
playbackRateBasedRebufferingAvoidanceSettings: {
308+
onBufferGapSize: 1.5,
309+
minPlaybackRate: 0.95,
310+
},
311+
},
306312
},
307313
arg,
308314
) as ILoadVideoOptions,

0 commit comments

Comments
 (0)