Skip to content

Commit

Permalink
Merge branch 'development' into sschr/prefBasedSelection_3961
Browse files Browse the repository at this point in the history
  • Loading branch information
dsilhavy authored Oct 10, 2022
2 parents 4c247c9 + 2a398d8 commit 3bb7a49
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 40 deletions.
1 change: 1 addition & 0 deletions contrib/akamai/controlbar/controlbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

.time-display{
float:left;
min-width: 72px;
}

.duration-display{
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ declare namespace dashjs {

on(type: AdaptationSetRemovedNoCapabilitiesEvent['type'], listener: (e: AdaptationSetRemovedNoCapabilitiesEvent) => void, scope?: object): void;

on(type: string, listener: (e: Event) => void, scope?: object): void;
on(type: string, listener: (e: Event) => void, scope?: object, options?:object): void;


off(type: string, listener: (e: any) => void, scope?: object): void;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dashjs",
"version": "4.5.0",
"version": "4.5.1",
"description": "A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.",
"author": "Dash Industry Forum",
"license": "BSD-3-Clause",
Expand Down
9 changes: 8 additions & 1 deletion src/streaming/MediaPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,13 @@ function MediaPlayer() {
}

let s = playbackController.getIsDynamic() ? getDVRSeekOffset(value) : value;

// For VoD limit the seek to the duration of the content
const videoElement = getVideoElement();
if (!playbackController.getIsDynamic() && videoElement.duration) {
s = Math.min(videoElement.duration, s);
}

playbackController.seek(s, false, false, true);
}

Expand Down Expand Up @@ -1996,7 +2003,7 @@ function MediaPlayer() {
* @return {object}
*/
function getCurrentSteeringResponseData() {
if(contentSteeringController) {
if (contentSteeringController) {
return contentSteeringController.getCurrentSteeringResponseData();
}
}
Expand Down
75 changes: 42 additions & 33 deletions src/streaming/controllers/BufferController.js
Original file line number Diff line number Diff line change
Expand Up @@ -541,54 +541,63 @@ function BufferController(config) {

function _getRangeAheadForPruning(targetTime, ranges) {
// if we do a seek behind the current play position we do need to prune ahead of the new play position
// we keep everything that is within bufferToKeepAhead but only if the buffer is continuous.
// Otherwise we have gaps once the seek is done which might trigger an unintentional gap jump
const endOfBuffer = ranges.end(ranges.length - 1) + BUFFER_END_THRESHOLD;
const continuousBufferTime = getContinuousBufferTimeForTargetTime(targetTime);

// This is the maximum range we keep ahead
const isLongFormContent = streamInfo.manifestInfo.duration >= settings.get().streaming.buffer.longFormContentDurationThreshold;
const bufferToKeepAhead = isLongFormContent ? settings.get().streaming.buffer.bufferTimeAtTopQualityLongForm : settings.get().streaming.buffer.bufferTimeAtTopQuality;
const aheadDiff = endOfBuffer - targetTime;

if (aheadDiff > bufferToKeepAhead) {
// Define the start time from which we will prune. If there is no continuous range from the targettime we start immediately at the target time
// Otherwise we set the start point to the end of the continuous range taking the maximum buffer to keep ahead into account
let rangeStart = !isNaN(continuousBufferTime) ? Math.min(continuousBufferTime, targetTime + bufferToKeepAhead) : targetTime;

let rangeStart = targetTime + bufferToKeepAhead;
// Ensure we keep full range of current fragment
const currentTimeRequest = fragmentModel.getRequests({
state: FragmentModel.FRAGMENT_MODEL_EXECUTED,
time: targetTime,
threshold: BUFFER_RANGE_CALCULATION_THRESHOLD
})[0];
// Check if we are done buffering, no need to prune then
if (rangeStart >= ranges.end(ranges.length - 1)) {
return null
}

if (currentTimeRequest) {
rangeStart = Math.max(currentTimeRequest.startTime + currentTimeRequest.duration, rangeStart);
}
// Ensure we keep full range of current fragment
const currentTimeRequest = fragmentModel.getRequests({
state: FragmentModel.FRAGMENT_MODEL_EXECUTED,
time: targetTime,
threshold: BUFFER_RANGE_CALCULATION_THRESHOLD
})[0];

// Never remove the contiguous range of targetTime in order to avoid flushes & reenqueues when the user doesn't want it
const avoidCurrentTimeRangePruning = settings.get().streaming.buffer.avoidCurrentTimeRangePruning;
if (avoidCurrentTimeRangePruning) {
for (let i = 0; i < ranges.length; i++) {
if (ranges.start(i) <= targetTime && targetTime <= ranges.end(i)
&& ranges.start(i) <= rangeStart && rangeStart <= ranges.end(i)) {
let oldRangeStart = rangeStart;
if (i + 1 < ranges.length) {
rangeStart = ranges.start(i+1);
} else {
rangeStart = ranges.end(i) + 1;
}
logger.debug('Buffered range [' + ranges.start(i) + ', ' + ranges.end(i) + '] overlaps with targetTime ' + targetTime + ' and range to be pruned [' + oldRangeStart + ', ' + endOfBuffer + '], using [' + rangeStart + ', ' + endOfBuffer +'] instead' + ((rangeStart < endOfBuffer) ? '' : ' (no actual pruning)'));
break;
if (currentTimeRequest) {
rangeStart = Math.max(currentTimeRequest.startTime + currentTimeRequest.duration, rangeStart);
}

// Never remove the contiguous range of targetTime in order to avoid flushes & reenqueues when the user doesn't want it
const avoidCurrentTimeRangePruning = settings.get().streaming.buffer.avoidCurrentTimeRangePruning;
if (avoidCurrentTimeRangePruning) {
for (let i = 0; i < ranges.length; i++) {
if (ranges.start(i) <= targetTime && targetTime <= ranges.end(i)
&& ranges.start(i) <= rangeStart && rangeStart <= ranges.end(i)) {
let oldRangeStart = rangeStart;
if (i + 1 < ranges.length) {
rangeStart = ranges.start(i + 1);
} else {
rangeStart = ranges.end(i) + 1;
}
logger.debug('Buffered range [' + ranges.start(i) + ', ' + ranges.end(i) + '] overlaps with targetTime ' + targetTime + ' and range to be pruned [' + oldRangeStart + ', ' + endOfBuffer + '], using [' + rangeStart + ', ' + endOfBuffer + '] instead' + ((rangeStart < endOfBuffer) ? '' : ' (no actual pruning)'));
break;
}
}

if (rangeStart < endOfBuffer) {
return {
start: rangeStart,
end: endOfBuffer
};
}
}

if (rangeStart < ranges.end(ranges.length - 1)) {
return {
start: rangeStart,
end: endOfBuffer
};
}
return null;
}


function _onPlaybackProgression() {
if (!replacingBuffer || (type === Constants.TEXT && textController.isTextEnabled())) {
_updateBufferLevel();
Expand Down
7 changes: 4 additions & 3 deletions src/streaming/controllers/GapController.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import FactoryMaker from '../../core/FactoryMaker';
import Debug from '../../core/Debug';
import Events from '../../core/events/Events';
import EventBus from '../../core/EventBus';
import Constants from '../constants/Constants';

const GAP_HANDLER_INTERVAL = 100;
const THRESHOLD_TO_STALLS = 10;
Expand Down Expand Up @@ -131,7 +132,7 @@ function GapController() {
*/
function _onBufferReplacementStarted(e) {
try {
if (e.streamId !== streamController.getActiveStreamInfo().id || !e.mediaType) {
if (e.streamId !== streamController.getActiveStreamInfo().id || (e.mediaType !== Constants.VIDEO && e.mediaType !== Constants.AUDIO)) {
return;
}

Expand Down Expand Up @@ -305,7 +306,7 @@ function GapController() {
* @private
*/
function _jumpGap(currentTime, playbackStalled = false) {
const enableStallFix = settings.get().streaming.gaps.enableStallFix;
const enableStallFix = settings.get().streaming.gaps.enableStallFix;
const stallSeek = settings.get().streaming.gaps.stallSeek;
const smallGapLimit = settings.get().streaming.gaps.smallGapLimit;
const jumpLargeGaps = settings.get().streaming.gaps.jumpLargeGaps;
Expand All @@ -332,7 +333,7 @@ function GapController() {
seekToPosition = parseFloat(playbackController.getStreamEndTime().toFixed(5));
jumpToStreamEnd = true;
}

if(enableStallFix && isNaN(seekToPosition) && playbackStalled && isNaN(nextRangeIndex) && _isTimeBuffered(ranges, currentTime)) {
if (stallSeek === 0) {
logger.warn(`Toggle play pause to break stall`);
Expand Down
8 changes: 7 additions & 1 deletion src/streaming/controllers/StreamController.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ function StreamController() {
errHandler, timelineConverter, streams, activeStream, protectionController, textController, protectionData,
autoPlay, isStreamSwitchingInProgress, hasMediaError, hasInitialisationError, mediaSource, videoModel,
playbackController, serviceDescriptionController, mediaPlayerModel, customParametersModel, isPaused,
initialPlayback, playbackEndedTimerInterval, bufferSinks, preloadingStreams, supportsChangeType, settings,
initialPlayback, initialSteeringRequest, playbackEndedTimerInterval, bufferSinks, preloadingStreams,
supportsChangeType, settings,
firstLicenseIsFetched, waitForPlaybackStartTimeout, providedStartTime, errorInformation;

function setup() {
Expand Down Expand Up @@ -708,6 +709,7 @@ function StreamController() {
const initialBufferLevel = mediaPlayerModel.getInitialBufferLevel();
const excludedStreamProcessors = [Constants.TEXT];
if (isNaN(initialBufferLevel) || initialBufferLevel <= playbackController.getBufferLevel(excludedStreamProcessors) || (adapter.getIsDynamic() && initialBufferLevel > playbackController.getLiveDelay())) {
initialPlayback = false;
_createPlaylistMetrics(PlayList.INITIAL_PLAYOUT_START_REASON);
playbackController.play();
}
Expand Down Expand Up @@ -774,6 +776,9 @@ function StreamController() {
}
if (initialPlayback) {
initialPlayback = false;
}
if (initialSteeringRequest) {
initialSteeringRequest = false;
// If this is the initial playback attempt and we have not yet triggered content steering now is the time
if (settings.get().streaming.applyContentSteering && !contentSteeringController.shouldQueryBeforeStart()) {
contentSteeringController.loadSteeringData();
Expand Down Expand Up @@ -1499,6 +1504,7 @@ function StreamController() {
hasMediaError = false;
hasInitialisationError = false;
initialPlayback = true;
initialSteeringRequest = true;
isPaused = false;
autoPlay = true;
playbackEndedTimerInterval = null;
Expand Down

0 comments on commit 3bb7a49

Please sign in to comment.