Skip to content

Commit

Permalink
Add rebuffering avoidance to the demo page
Browse files Browse the repository at this point in the history
  • Loading branch information
peaBerberian committed Nov 15, 2024
1 parent 1521d0a commit 752d5f2
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 0 deletions.
104 changes: 104 additions & 0 deletions demo/scripts/components/Options/BufferOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ const DEFAULT_MAX_BUFFER_AHEAD = DEFAULT_VALUES.player.maxBufferAhead;
const DEFAULT_MAX_BUFFER_BEHIND = DEFAULT_VALUES.player.maxBufferBehind;
const DEFAULT_MAX_VIDEO_BUFFER_SIZE = DEFAULT_VALUES.player.maxVideoBufferSize;
const DEFAULT_WANTED_BUFFER_AHEAD = DEFAULT_VALUES.player.wantedBufferAhead;
const DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE =
DEFAULT_VALUES.loadVideo.experimentalOptions
.playbackRateBasedRebufferingAvoidanceSettings.onBufferGapSize;
const DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE =
DEFAULT_VALUES.loadVideo.experimentalOptions
.playbackRateBasedRebufferingAvoidanceSettings.minPlaybackRate;

/**
* @param {Object} props
Expand All @@ -19,19 +25,27 @@ function BufferOptions({
maxVideoBufferSize,
maxBufferAhead,
maxBufferBehind,
rebufferingAvoidanceBufferGapSize,
rebufferingAvoidanceMinPlaybackRate,
onWantedBufferAheadChange,
onMaxVideoBufferSizeChange,
onMaxBufferAheadChange,
onMaxBufferBehindChange,
onRebufferingAvoidanceBufferGapSizeChange,
onRebufferingAvoidanceMinPlaybackRateChange,
}: {
wantedBufferAhead: number;
maxVideoBufferSize: number;
maxBufferAhead: number;
maxBufferBehind: number;
rebufferingAvoidanceBufferGapSize: number;
rebufferingAvoidanceMinPlaybackRate: number;
onWantedBufferAheadChange: (newVal: number) => void;
onMaxVideoBufferSizeChange: (newVal: number) => void;
onMaxBufferBehindChange: (newVal: number) => void;
onMaxBufferAheadChange: (newVal: number) => void;
onRebufferingAvoidanceBufferGapSizeChange: (newVal: number) => void;
onRebufferingAvoidanceMinPlaybackRateChange: (newVal: number) => void;
}): JSX.Element {
/* Value of the `wantedBufferAhead` input */
const [wantedBufferAheadStr, setWantedBufferAheadStr] = useState(
Expand All @@ -45,6 +59,14 @@ function BufferOptions({
const [maxBufferBehindStr, setMaxBufferBehindStr] = useState(String(maxBufferBehind));
/* Value of the `maxBufferAhead` input */
const [maxBufferAheadStr, setMaxBufferAheadStr] = useState(String(maxBufferAhead));
/* Value of the `rebufferingAvoidanceBufferGapSize` input */
const [rebufferingAvoidanceBufferGapSizeStr, setRebufferingAvoidanceBufferGapSizeStr] =
useState(String(rebufferingAvoidanceBufferGapSize));
/* Value of the `rebufferingAvoidanceMinPlaybackRate` input */
const [
rebufferingAvoidanceMinPlaybackRateStr,
setRebufferingAvoidanceMinPlaybackRateStr,
] = useState(String(rebufferingAvoidanceMinPlaybackRate));
/*
* Keep track of the "limit maxBufferAhead" toggle:
* `false` == checkbox enabled
Expand All @@ -66,6 +88,7 @@ function BufferOptions({
const [isMaxVideoBufferSizeLimited, setMaxVideoBufferSizeLimit] = useState(
maxVideoBufferSize !== Infinity,
);
const isRebufferingAvoidanceEnabled = rebufferingAvoidanceBufferGapSize !== 0;

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

// Update `rebufferingAvoidanceBufferGapSize` when its linked text change
useEffect(() => {
// Note that this unnecessarily also run on first render - there seem to be
// no quick and easy way to disable this in react.
// This is not too problematic so I put up with it.
let newVal = parseFloat(rebufferingAvoidanceBufferGapSizeStr);
newVal = isNaN(newVal) ? DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE : newVal;
onRebufferingAvoidanceBufferGapSizeChange(newVal);
}, [rebufferingAvoidanceBufferGapSizeStr]);

// Update `rebufferingAvoidanceMinPlaybackRate` when its linked text change
useEffect(() => {
// Note that this unnecessarily also run on first render - there seem to be
// no quick and easy way to disable this in react.
// This is not too problematic so I put up with it.
let newVal = parseFloat(rebufferingAvoidanceMinPlaybackRateStr);
newVal = isNaN(newVal) ? DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE : newVal;
onRebufferingAvoidanceMinPlaybackRateChange(newVal);
}, [rebufferingAvoidanceMinPlaybackRateStr]);

const onChangeLimitMaxBufferAhead = useCallback((isNotLimited: boolean) => {
if (isNotLimited) {
setMaxBufferAheadLimit(false);
Expand Down Expand Up @@ -128,6 +171,14 @@ function BufferOptions({
}
}, []);

const onRebufferingAvoidanceEnableClick = useCallback((isEnabled: boolean) => {
if (isEnabled) {
setRebufferingAvoidanceBufferGapSizeStr("0");
} else {
setRebufferingAvoidanceBufferGapSizeStr("1.5");
}
}, []);

const onWantedBufferAheadResetClick = React.useCallback(() => {
setWantedBufferAheadStr(String(DEFAULT_WANTED_BUFFER_AHEAD));
}, []);
Expand All @@ -147,6 +198,18 @@ function BufferOptions({
setMaxBufferBehindLimit(DEFAULT_MAX_BUFFER_BEHIND !== Infinity);
}, []);

const onRebufferingAvoidanceBufferGapSizeResetClick = React.useCallback(() => {
setRebufferingAvoidanceBufferGapSizeStr(
String(DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE),
);
}, []);

const onRebufferingAvoidanceMinPlaybackRateResetClick = React.useCallback(() => {
setRebufferingAvoidanceMinPlaybackRateStr(
String(DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE),
);
}, []);

return (
<Fragment>
<li>
Expand Down Expand Up @@ -242,6 +305,47 @@ function BufferOptions({
: `Manually cleaning data ${maxBufferBehind} second(s) behind the current position`}
</span>
</li>
<li>
<PlayerOptionNumberInput
ariaLabel="Playback Rate Based Rebuffering Avoidance Buffer Size option"
label="playbackRateBasedRebufferingAvoidanceBufferSize"
title="Rebuffering Avoidance: Buffer Size"
valueAsString={rebufferingAvoidanceBufferGapSizeStr}
defaultValueAsNumber={DEFAULT_REBUFFERING_AVOIDANCE_BUFFER_GAP_SIZE}
isDisabled={!isRebufferingAvoidanceEnabled}
onUpdateValue={setRebufferingAvoidanceBufferGapSizeStr}
onResetClick={onRebufferingAvoidanceBufferGapSizeResetClick}
/>
<Checkbox
className="playerOptionsCheckBox"
ariaLabel="Do not enable Playback Rate-Based Rebuffering Avoidance"
name="rebufferingAvoidanceEnable"
checked={!isRebufferingAvoidanceEnabled}
onChange={onRebufferingAvoidanceEnableClick}
>
Disable
</Checkbox>
<span className="option-desc">
{rebufferingAvoidanceBufferGapSize <= 0 || !isRebufferingAvoidanceEnabled
? "No triggering Playback-Rate-based rebuffering Avoidance"
: `Starting rebuffering avoidance strategy once ${rebufferingAvoidanceBufferGapSize} second(s) is left in the buffer`}
</span>
<PlayerOptionNumberInput
ariaLabel="Playback Rate Based Rebuffering Avoidance Min Playback Rate option"
label="playbackRateBasedRebufferingAvoidanceMinPlaybackRate"
title="Rebuffering Avoidance: Playback Rate"
valueAsString={rebufferingAvoidanceMinPlaybackRateStr}
defaultValueAsNumber={DEFAULT_REBUFFERING_AVOIDANCE_MIN_PLAYBACK_RATE}
isDisabled={!isRebufferingAvoidanceEnabled}
onUpdateValue={setRebufferingAvoidanceMinPlaybackRateStr}
onResetClick={onRebufferingAvoidanceMinPlaybackRateResetClick}
/>
<span className="option-desc">
{rebufferingAvoidanceBufferGapSize <= 0 || !isRebufferingAvoidanceEnabled
? "No triggering Playback-Rate-based rebuffering Avoidance"
: `Rebuffering avoidance strategies will play at ${rebufferingAvoidanceMinPlaybackRate}x the speed once ${rebufferingAvoidanceBufferGapSize} second(s) is left in the buffer`}
</span>
</li>
</Fragment>
);
}
Expand Down
67 changes: 67 additions & 0 deletions demo/scripts/controllers/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function Settings({
checkManifestIntegrity,
requestConfig,
onCodecSwitch,
experimentalOptions,
} = loadVideoOptions;
const cmcdCommunicationMethod = cmcd?.communicationType ?? "disabled";
const { manifest: manifestRequestConfig, segment: segmentRequestConfig } =
Expand Down Expand Up @@ -313,6 +314,58 @@ function Settings({
[playerOptions],
);

const onRebufferingAvoidanceBufferGapSizeChange = useCallback(
(rebufferingAvoidanceBufferGapSize: number) => {
updateLoadVideoOptions((prevOptions) => {
if (
rebufferingAvoidanceBufferGapSize ===
prevOptions.experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
.onBufferGapSize
) {
return prevOptions;
}
return Object.assign({}, prevOptions, {
...prevOptions.experimentalOptions,
experimentalOptions: {
playbackRateBasedRebufferingAvoidanceSettings: {
onBufferGapSize: rebufferingAvoidanceBufferGapSize,
minPlaybackRate:
prevOptions.experimentalOptions
.playbackRateBasedRebufferingAvoidanceSettings.minPlaybackRate,
},
},
});
});
},
[playerOptions],
);

const onRebufferingAvoidanceMinPlaybackRateChange = useCallback(
(rebufferingAvoidanceMinPlaybackRate: number) => {
updateLoadVideoOptions((prevOptions) => {
if (
rebufferingAvoidanceMinPlaybackRate ===
prevOptions.experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
.minPlaybackRate
) {
return prevOptions;
}
return Object.assign({}, prevOptions, {
experimentalOptions: {
...prevOptions.experimentalOptions,
playbackRateBasedRebufferingAvoidanceSettings: {
onBufferGapSize:
prevOptions.experimentalOptions
.playbackRateBasedRebufferingAvoidanceSettings.onBufferGapSize,
minPlaybackRate: rebufferingAvoidanceMinPlaybackRate,
},
},
});
});
},
[playerOptions],
);

const onMaxVideoBufferSizeChange = useCallback(
(maxVideoBufferSize: number) => {
updatePlayerOptions((prevOptions) => {
Expand Down Expand Up @@ -432,10 +485,24 @@ function Settings({
maxVideoBufferSize={maxVideoBufferSize}
maxBufferAhead={maxBufferAhead}
maxBufferBehind={maxBufferBehind}
rebufferingAvoidanceBufferGapSize={
experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
.onBufferGapSize
}
rebufferingAvoidanceMinPlaybackRate={
experimentalOptions.playbackRateBasedRebufferingAvoidanceSettings
.minPlaybackRate
}
onWantedBufferAheadChange={onWantedBufferAheadChange}
onMaxBufferAheadChange={onMaxBufferAheadChange}
onMaxBufferBehindChange={onMaxBufferBehindChange}
onMaxVideoBufferSizeChange={onMaxVideoBufferSizeChange}
onRebufferingAvoidanceBufferGapSizeChange={
onRebufferingAvoidanceBufferGapSizeChange
}
onRebufferingAvoidanceMinPlaybackRateChange={
onRebufferingAvoidanceMinPlaybackRateChange
}
/>
</Option>
</div>
Expand Down
7 changes: 7 additions & 0 deletions demo/scripts/lib/defaultOptionsValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
ICmcdOptions,
IConstructorOptions,
ILoadVideoOptions,
IPlaybackRateBasedRebufferingAvoidanceSettings,
} from "../../../src/public_types";

const defaultOptionsValues = {
Expand Down Expand Up @@ -31,6 +32,12 @@ const defaultOptionsValues = {
},
},
onCodecSwitch: "continue",
experimentalOptions: {
playbackRateBasedRebufferingAvoidanceSettings: {
onBufferGapSize: 0,
minPlaybackRate: 0.95,
} as IPlaybackRateBasedRebufferingAvoidanceSettings,
},
},
} satisfies {
player: IConstructorOptions;
Expand Down
6 changes: 6 additions & 0 deletions demo/scripts/modules/player/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ const PlayerModule = declareModule(
{
mode: state.get("relyOnWorker") ? "auto" : "main",
textTrackElement,
experimentalOptions: {
playbackRateBasedRebufferingAvoidanceSettings: {
onBufferGapSize: 1.5,
minPlaybackRate: 0.95,
},
},
},
arg,
) as ILoadVideoOptions,
Expand Down

0 comments on commit 752d5f2

Please sign in to comment.