Skip to content

Commit

Permalink
Minor fixes and documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
jeoliva committed Jun 7, 2018
1 parent 7c9cba3 commit 715e75a
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 42 deletions.
2 changes: 1 addition & 1 deletion build/typings/index.d.ts
Expand Up @@ -123,7 +123,7 @@ declare namespace dashjs {
isMuted(): boolean;
setVolume(value: number): void;
getVolume(): number;
time(streamId: string | undefined): number;
time(streamId?: string): number;
duration(): number;
timeAsUTC(): number;
durationAsUTC(): number;
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Expand Up @@ -123,7 +123,7 @@ declare namespace dashjs {
isMuted(): boolean;
setVolume(value: number): void;
getVolume(): number;
time(streamId: string | undefined): number;
time(streamId?: string): number;
duration(): number;
timeAsUTC(): number;
durationAsUTC(): number;
Expand Down
4 changes: 2 additions & 2 deletions samples/dash-if-reference-player/app/sources.json
Expand Up @@ -74,15 +74,15 @@
"name": "Low Latency (Single-Rate)",
"bufferConfig" : {
"lowLatencyMode": true,
"liveDelay": 3
"liveDelay": 3.5
}
},
{
"url": "https://vm2.dashif.org/livesim-chunked/chunkdur_1/ato_7/testpic4_8s/Manifest.mpd",
"name": "Low Latency (Multi-Rate)",
"bufferConfig" : {
"lowLatencyMode": true,
"liveDelay": 3
"liveDelay": 3.5
}
},
{
Expand Down
16 changes: 13 additions & 3 deletions src/streaming/MediaPlayer.js
Expand Up @@ -484,13 +484,22 @@ function MediaPlayer() {
}

/**
* Use this method to set the playback rate that will be used when catching up with live stream. Set 1 to disable the feature.
* @param {number} value
* Use this method to set the catch up rate, as a percentage, for low latency live streams. In low latency mode,
* when measured latency is higher than the target one ({@link module:MediaPlayer#setLiveDelay setLiveDelay()}),
* dash.js increases playback rate the percentage defined with this method until target is reached.
*
* Valid values for catch up rate are in range 0-20%. Set it to 0% to turn off live catch up feature.
*
* Note: Catch-up mechanism is only applied when playing low latency live streams.
*
* @param {number} value Percentage in which playback rate is increased when live catch up mechanism is activated.
* @memberof module:MediaPlayer
* @see {@link module:MediaPlayer#setLiveDelay setLiveDelay()}
* @default {number} 0.05
* @instance
*/
function setCatchUpPlaybackRate(value) {
if (isNaN(value) || value < 1 || value > 1.20) {
if (isNaN(value) || value < 0.0 || value > 0.20) {
throw PLAYBACK_CATCHUP_RATE_BAD_ARGUMENT_ERROR;
}
playbackController.setCatchUpPlaybackRate(value);
Expand All @@ -499,6 +508,7 @@ function MediaPlayer() {
/**
* Returns the current catchup playback rate.
* @returns {number}
* @see {@link module:MediaPlayer#setCatchUpPlaybackRate setCatchUpPlaybackRate()}
* @memberof module:MediaPlayer
* @instance
*/
Expand Down
18 changes: 11 additions & 7 deletions src/streaming/MediaPlayerEvents.js
Expand Up @@ -214,18 +214,22 @@ class MediaPlayerEvents extends EventsBase {
*/
this.CAN_PLAY = 'canPlay';


/**
* Sent live catch up stops and playback rate goes back to normal
* @event MediaPlayerEvents#PLAYBACK_CATCHUP_END
* Sent when live catch mechanism has been activated, which implies the measured latency of the low latency
* stream that is been played has gone beyond the target one.
* @see {@link module:MediaPlayer#setCatchUpPlaybackRate setCatchUpPlaybackRate()}
* @see {@link module:MediaPlayer#setLiveDelay setLiveDelay()}
* @event MediaPlayerEvents#PLAYBACK_CATCHUP_START
*/
this.PLAYBACK_CATCHUP_END = 'playbackCatchupEnd';
this.PLAYBACK_CATCHUP_START = 'playbackCatchupStart';

/**
* Sent when playing live and buffer is too long, the player starts catching up by accelerating.
* @event MediaPlayerEvents#PLAYBACK_CATCHUP_START
* Sent live catch up mechanism has been deactivated.
* @see {@link module:MediaPlayer#setCatchUpPlaybackRate setCatchUpPlaybackRate()}
* @see {@link module:MediaPlayer#setLiveDelay setLiveDelay()}
* @event MediaPlayerEvents#PLAYBACK_CATCHUP_END
*/
this.PLAYBACK_CATCHUP_START = 'playbackCatchupStart';
this.PLAYBACK_CATCHUP_END = 'playbackCatchupEnd';

/**
* Sent when playback completes.
Expand Down
68 changes: 40 additions & 28 deletions src/streaming/controllers/PlaybackController.js
Expand Up @@ -37,8 +37,11 @@ import FactoryMaker from '../../core/FactoryMaker';
import Debug from '../../core/Debug';

const LIVE_UPDATE_PLAYBACK_TIME_INTERVAL_MS = 500;
const DEFAULT_CATCHUP_PLAYBACK_RATE = 1.05;
const LIVE_CATCHUP_THRESHOLD = 0.5;
const DEFAULT_CATCHUP_PLAYBACK_RATE = 0.05;

// Start catching up mechanism for low latency live streaming
// when latency goes beyong targetDelay * (1 + LIVE_CATCHUP_START_THRESHOLD)
const LIVE_CATCHUP_START_THRESHOLD = 0.35;

function PlaybackController() {

Expand Down Expand Up @@ -85,8 +88,6 @@ function PlaybackController() {
eventBus.on(Events.BYTES_APPENDED_END_FRAGMENT, onBytesAppended, this);
eventBus.on(Events.BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
eventBus.on(Events.PERIOD_SWITCH_STARTED, onPeriodSwitchStarted, this);
eventBus.on(Events.PLAYBACK_CATCHUP_END, onPlaybackCatchUpEnd, this);
eventBus.on(Events.PLAYBACK_CATCHUP_START, onPlaybackCatchUpStart, this);
eventBus.on(Events.PLAYBACK_PROGRESS, onPlaybackProgression, this);
eventBus.on(Events.PLAYBACK_TIME_UPDATED, onPlaybackProgression, this);

Expand Down Expand Up @@ -173,6 +174,11 @@ function PlaybackController() {

function setCatchUpPlaybackRate(value) {
catchUpPlaybackRate = value;

// If value == 0.0, deactivate catchup mechanism
if (value === 0.0 && getPlaybackRate() > 1.0) {
stopPlaybackCatchUp();
}
}

function getCatchUpPlaybackRate() {
Expand Down Expand Up @@ -238,18 +244,33 @@ function PlaybackController() {
return ((Math.round(new Date().getTime() - (currentTime * 1000 + availabilityStartTime))) / 1000).toFixed(3);
}

function onPlaybackCatchUpStart() {
function startPlaybackCatchUp() {
if (videoModel) {
logger.info('onPlaybackCatchUpStart setting playback rate to', getCatchUpPlaybackRate());
originalPlaybackRate = originalPlaybackRate || getPlaybackRate();
videoModel.getElement().playbackRate = getCatchUpPlaybackRate();
const playbackRate = 1 + getCatchUpPlaybackRate();
const currentRate = getPlaybackRate();
if (playbackRate !== currentRate) {
catchingUp = true;

logger.info('Starting live catchup mechanism. Setting playback rate to', playbackRate);
originalPlaybackRate = currentRate;
videoModel.getElement().playbackRate = playbackRate;

eventBus.trigger(Events.PLAYBACK_CATCHUP_START, { sender: instance });
}
}
}

function onPlaybackCatchUpEnd() {
function stopPlaybackCatchUp() {
if (videoModel) {
logger.info('onPlaybackCatchUpEnd setting playback rate to', originalPlaybackRate || 1);
videoModel.getElement().playbackRate = originalPlaybackRate || 1;
const playbackRate = originalPlaybackRate || 1;
if (playbackRate !== getPlaybackRate()) {
catchingUp = false;

logger.info('Stopping live catchup mechanism. Setting playback rate to', playbackRate);
videoModel.getElement().playbackRate = playbackRate;

eventBus.trigger(Events.PLAYBACK_CATCHUP_END, { sender: instance });
}
}
}

Expand All @@ -267,8 +288,6 @@ function PlaybackController() {
eventBus.off(Events.BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
eventBus.off(Events.BYTES_APPENDED_END_FRAGMENT, onBytesAppended, this);
eventBus.off(Events.PERIOD_SWITCH_STARTED, onPeriodSwitchStarted, this);
eventBus.off(Events.PLAYBACK_CATCHUP_END, onPlaybackCatchUpEnd, this);
eventBus.off(Events.PLAYBACK_CATCHUP_START, onPlaybackCatchUpStart, this);
eventBus.off(Events.PLAYBACK_PROGRESS, onPlaybackProgression, this);
eventBus.off(Events.PLAYBACK_TIME_UPDATED, onPlaybackProgression, this);
stopUpdatingWallclockTime();
Expand Down Expand Up @@ -549,28 +568,21 @@ function PlaybackController() {
}

function onPlaybackProgression() {
if (needToCatchUp() && !catchingUp) {
catchingUp = true;
eventBus.trigger(Events.PLAYBACK_CATCHUP_START, { sender: instance });
} else if (stopCatchingUp()) {
catchingUp = false;
eventBus.trigger(Events.PLAYBACK_CATCHUP_END, { sender: instance });
if (isDynamic && mediaPlayerModel.getLowLatencyEnabled() && getCatchUpPlaybackRate() > 0.0) {
if (!catchingUp && needToCatchUp()) {
startPlaybackCatchUp();
} else if (stopCatchingUp()) {
stopPlaybackCatchUp();
}
}
}

function needToCatchUp() {
if (getIsDynamic() && getCatchUpPlaybackRate() !== 1) {
return getCurrentLiveLatency() > (mediaPlayerModel.getLiveDelay() * (1 + LIVE_CATCHUP_THRESHOLD));
}
return false;
return getCurrentLiveLatency() > (mediaPlayerModel.getLiveDelay() * (1 + LIVE_CATCHUP_START_THRESHOLD));
}

function stopCatchingUp() {
if (catchingUp && getIsDynamic()) {
return getCurrentLiveLatency() <= (mediaPlayerModel.getLiveDelay() + LIVE_CATCHUP_THRESHOLD );
}

return false;
return getCurrentLiveLatency() <= (mediaPlayerModel.getLiveDelay() );
}

function onBytesAppended(e) {
Expand Down

0 comments on commit 715e75a

Please sign in to comment.