Skip to content

Commit

Permalink
fix(FEC-11136): Tizen 4 got stuck on the beginning of the media (#140)
Browse files Browse the repository at this point in the history
Issue: Tizen 4 has stalled on the beginning of the media/after first seek we want to make sure the media wouldn't stop.
Solution: make a small seeks until playback keeps playing.
  • Loading branch information
Yuvalke authored Apr 27, 2021
1 parent 5f4df73 commit 13b9fb6
Showing 1 changed file with 88 additions and 6 deletions.
94 changes: 88 additions & 6 deletions src/dash-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@ const ShakaEvent: ShakaEventType = {
*/
const ABR_RESTRICTION_UPDATE_INTERVAL = 1000;

/**
* the interval for stall detection
* @type {number}
* @const
*/
const STALL_DETECTION_INTERVAL = 2000;

/**
* the threshold needed to break the stall
* @type {number}
* @const
*/
const STALL_BREAK_THRESHOLD = 0.1;

/**
* the number of stalls until we stop
* @type {number}
* @const
*/
const MAX_NUMBER_OF_STALLS = 10;

/**
* Adapter of shaka lib for dash content
* @classdesc
Expand Down Expand Up @@ -144,6 +165,26 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
*/
_videoSizeUpdateTimer: ?IntervalID = null;

/**
* stall interval to break the stall on Smart TV
* @type {null|IntervalID}
* @private
*/
_stallInterval: ?IntervalID = null;

/**
* start time requested
* @type {null|number}
* @private
*/
_startTime: ?number;

/**
* playback started to play
* @type {boolean}
* @private
*/
_isPlaybackStarted: boolean = false;
/**
* 3016 is the number of the video error at shaka, we already listens to it in the html5 class
* @member {number} - VIDEO_ERROR_CODE
Expand Down Expand Up @@ -205,6 +246,9 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
if (Utils.Object.hasPropertyPath(config, 'text.useShakaTextTrackDisplay')) {
adapterConfig.useShakaTextTrackDisplay = Utils.Object.getPropertyPath(config, 'text.useShakaTextTrackDisplay');
}
if (Utils.Object.hasPropertyPath(config, 'streaming.forceBreakStall')) {
adapterConfig.forceBreakStall = Utils.Object.getPropertyPath(config, 'streaming.forceBreakStall');
}
if (Utils.Object.hasPropertyPath(config, 'sources.options')) {
const options = config.sources.options;
adapterConfig.forceRedirectExternalStreams = options.forceRedirectExternalStreams;
Expand Down Expand Up @@ -366,10 +410,44 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
}
this._maybeSetFilters();
this._maybeSetDrmConfig();
this._maybeBreakStalls();
this._shaka.configure(this._config.shakaConfig);
this._addBindings();
}

_clearStallInterval(): void {
if (this._stallInterval) {
clearInterval(this._stallInterval);
this._stallInterval = null;
}
}

_stallHandler(): void {
this._clearStallInterval();
let stallHandlerCounter = 0;
let lastUpdateTime = !this._isPlaybackStarted && this._startTime ? this._startTime : this._videoElement.currentTime;
this._stallInterval = setInterval(() => {
if (lastUpdateTime === this._videoElement.currentTime && stallHandlerCounter++ < MAX_NUMBER_OF_STALLS) {
DashAdapter._logger.debug('stall found, break the stall');
this._videoElement.currentTime = parseFloat(this._videoElement.currentTime.toFixed(1)) + STALL_BREAK_THRESHOLD;
} else {
this._clearStallInterval();
}
lastUpdateTime = this._videoElement.currentTime;
}, STALL_DETECTION_INTERVAL);
}

/**
* register to event to break the stalls on smart TV
* @returns {void}
* @private
*/
_maybeBreakStalls(): void {
if (this._config.forceBreakStall) {
this._eventManager.listen(this._videoElement, EventType.STALLED, () => this._stallHandler());
}
}

/**
* get the redirected URL
* @param {string} url - The url to check for redirection
Expand Down Expand Up @@ -612,9 +690,11 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
this._eventManager.listen(this._shaka, ShakaEvent.DRM_SESSION_UPDATE, this._adapterEventsBindings.drmsessionupdate);
this._eventManager.listen(this._videoElement, EventType.WAITING, this._adapterEventsBindings.waiting);
this._eventManager.listen(this._videoElement, EventType.PLAYING, this._adapterEventsBindings.playing);
this._eventManager.listenOnce(this._videoElement, EventType.PLAYING, () =>
this._eventManager.listen(this._shaka, ShakaEvent.BUFFERING, this._adapterEventsBindings.buffering)
);
this._eventManager.listenOnce(this._videoElement, EventType.PLAYING, () => {
this._isPlaybackStarted = true;
this._eventManager.listen(this._shaka, ShakaEvent.BUFFERING, this._adapterEventsBindings.buffering);
});

// called when a resource is downloaded
this._shaka.getNetworkingEngine().registerResponseFilter((type, response) => {
switch (type) {
Expand Down Expand Up @@ -660,12 +740,12 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
this._loadPromise = new Promise((resolve, reject) => {
if (this._sourceObj && this._sourceObj.url) {
this._trigger(EventType.ABR_MODE_CHANGED, {mode: this.isAdaptiveBitrateEnabled() ? 'auto' : 'manual'});
let shakaStartTime = startTime && startTime > -1 ? startTime : undefined;
shakaStartTime = isNaN(this._lastTimeDetach) ? shakaStartTime : this._lastTimeDetach;
this._startTime = startTime && startTime > -1 ? startTime : undefined;
this._startTime = isNaN(this._lastTimeDetach) ? this._startTime : this._lastTimeDetach;
this._lastTimeDetach = NaN;
this._maybeGetRedirectedUrl(this._sourceObj.url)
.then(url => {
return this._shaka.load(url, shakaStartTime);
return this._shaka.load(url, this._startTime);
})
.then(() => {
const data = {tracks: this._getParsedTracks()};
Expand Down Expand Up @@ -733,6 +813,8 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
this._responseFilterError = false;
this._manifestParser = null;
this._thumbnailController = null;
this._isPlaybackStarted = false;
this._clearStallInterval();
this._clearVideoUpdateTimer();
if (this._eventManager) {
this._eventManager.removeAll();
Expand Down

0 comments on commit 13b9fb6

Please sign in to comment.