Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions demo/full/scripts/modules/player/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ function linkPlayerEventsToState(
stopPositionUpdates();

// use an interval for current position
positionUpdatesInterval = window.setInterval(() => {
positionUpdatesInterval = window.setInterval(
updatePositionInfo,
POSITION_UPDATES_INTERVAL);

updatePositionInfo();

function updatePositionInfo() {
const position = player.getPosition();
const duration = player.getVideoDuration();
const videoTrack = player.getVideoTrack();
Expand All @@ -68,7 +74,7 @@ function linkPlayerEventsToState(
videoTrack.trickModeTracks !== undefined &&
videoTrack.trickModeTracks.length > 0,
});
}, POSITION_UPDATES_INTERVAL);
}
}

function stopPositionUpdates() {
Expand Down
11 changes: 7 additions & 4 deletions src/core/init/media_source_content_initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import getInitialTime, {
import getLoadedReference from "./utils/get_loaded_reference";
import performInitialSeekAndPlay from "./utils/initial_seek_and_play";
import initializeContentDecryption from "./utils/initialize_content_decryption";
import MediaDurationUpdater from "./utils/media_duration_updater";
import MediaSourceDurationUpdater from "./utils/media_source_duration_updater";
import RebufferingController from "./utils/rebuffering_controller";
import streamEventsEmitter from "./utils/stream_events_emitter";
import listenToMediaError from "./utils/throw_on_media_error";
Expand Down Expand Up @@ -644,9 +644,9 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
cancelSignal : CancellationSignal
) : ContentTimeBoundariesObserver {
/** Maintains the MediaSource's duration up-to-date with the Manifest */
const mediaDurationUpdater = new MediaDurationUpdater(manifest, mediaSource);
const mediaSourceDurationUpdater = new MediaSourceDurationUpdater(mediaSource);
cancelSignal.register(() => {
mediaDurationUpdater.stop();
mediaSourceDurationUpdater.stopUpdating();
});
/** Allows to cancel a pending `end-of-stream` operation. */
let endOfStreamCanceller : TaskCanceller | null = null;
Expand All @@ -664,7 +664,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
this.trigger("activePeriodChanged", { period });
});
contentTimeBoundariesObserver.addEventListener("durationUpdate", (newDuration) => {
mediaDurationUpdater.updateKnownDuration(newDuration);
mediaSourceDurationUpdater.updateDuration(newDuration.duration, !newDuration.isEnd);
});
contentTimeBoundariesObserver.addEventListener("endOfStream", () => {
if (endOfStreamCanceller === null) {
Expand All @@ -681,6 +681,9 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
endOfStreamCanceller = null;
}
});
const currentDuration = contentTimeBoundariesObserver.getCurrentDuration();
mediaSourceDurationUpdater.updateDuration(currentDuration.duration,
!currentDuration.isEnd);
return contentTimeBoundariesObserver;
}

Expand Down
56 changes: 46 additions & 10 deletions src/core/init/utils/content_time_boundaries_observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,20 @@ export default class ContentTimeBoundariesObserver
}, { includeLastObservation: true, clearSignal: cancelSignal });

manifest.addEventListener("manifestUpdate", () => {
this.trigger("durationUpdate", getManifestDuration());
this.trigger("durationUpdate", this._getManifestDuration());
if (cancelSignal.isCancelled()) {
return;
}
this._checkEndOfStream();
}, cancelSignal);
}

function getManifestDuration() : number | undefined {
return manifest.isDynamic ?
maximumPositionCalculator.getMaximumAvailablePosition() :
maximumPositionCalculator.getEndingPosition();
}
/**
* Returns an estimate of the current duration of the content.
* @returns {Object}
*/
public getCurrentDuration() : IDurationItem {
return this._getManifestDuration();
}

/**
Expand Down Expand Up @@ -154,9 +156,12 @@ export default class ContentTimeBoundariesObserver
this._maximumPositionCalculator
.updateLastVideoAdaptation(adaptation);
}
const newDuration = this._manifest.isDynamic ?
this._maximumPositionCalculator.getMaximumAvailablePosition() :
this._maximumPositionCalculator.getEndingPosition();
const endingPosition = this._maximumPositionCalculator.getEndingPosition();
const newDuration = endingPosition !== undefined ?
{ isEnd: true,
duration: endingPosition } :
{ isEnd: false,
duration: this._maximumPositionCalculator.getMaximumAvailablePosition() };
this.trigger("durationUpdate", newDuration);
}
}
Expand Down Expand Up @@ -306,6 +311,15 @@ export default class ContentTimeBoundariesObserver
}
}

private _getManifestDuration() : IDurationItem {
const endingPosition = this._maximumPositionCalculator.getEndingPosition();
return endingPosition !== undefined ?
{ isEnd: true,
duration: endingPosition } :
{ isEnd: false,
duration: this._maximumPositionCalculator.getMaximumAvailablePosition() };
}

private _lazilyCreateActiveStreamInfo(bufferType : IBufferType) : IActiveStreamsInfo {
let streamInfo = this._activeStreams.get(bufferType);
if (streamInfo === undefined) {
Expand Down Expand Up @@ -334,6 +348,28 @@ export default class ContentTimeBoundariesObserver
}
}

export interface IDurationItem {
/**
* The new maximum known position (note that this is the ending position
* currently known of the current content, it might be superior to the last
* position at which segments are available and it might also evolve over
* time), in seconds.
*/
duration : number;
/**
* If `true`, the communicated `duration` is the actual end of the content.
* It may still be updated due to a track change or to add precision, but it
* is still a (rough) estimate of the maximum position that content should
* have.
*
* If `false`, this is the currently known maximum position associated to
* the content, but the content is still evolving (typically, new media
* segments are still being generated) and as such it can still have a
* longer duration in the future.
*/
isEnd : boolean;
}

/**
* Events triggered by a `ContentTimeBoundariesObserver` where the keys are the
* event names and the value is the payload of those events.
Expand All @@ -347,7 +383,7 @@ export interface IContentTimeBoundariesObserverEvent {
* Triggered when the duration of the currently-playing content became known
* or changed.
*/
durationUpdate : number | undefined;
durationUpdate : IDurationItem;
/**
* Triggered when the last possible chronological segment for all types of
* buffers has either been pushed or is being pushed to the corresponding
Expand Down
Loading