Skip to content

Commit

Permalink
fix(FEC-11697): 2 captions are selected in the menu (#161)
Browse files Browse the repository at this point in the history
see kaltura/playkit-js#633

**in addition regardless of the original issue** 
add error handling on load() method.
**issue:**  the promise will remain 'pending' forever ... in case an manifest loading error
Since the promise resolving returned from the load() rely on Hlsjs.Events.MANIFEST_LOADED event https://github.com/kaltura/playkit-js-hls/blob/master/src/hls-adapter.js#L140 to be resolved which is not fired in case of en error
**fix:** call promise reject in case of fatal error and still pending promise

solves: FEC-11697 and FEC-11893

related pr: 
kaltura/playkit-js-dash#182
kaltura/playkit-js#633
  • Loading branch information
TasvirChi authored and tasvirchi-gitaction committed Mar 2, 2022
1 parent dceb294 commit 12091d4
Show file tree
Hide file tree
Showing 6 changed files with 366 additions and 299 deletions.
4 changes: 2 additions & 2 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const launchers = {
module.exports = function (config) {
let karmaConf = {
logLevel: config.LOG_INFO,
browserNoActivityTimeout: 90000,
browsers: ['Chrome', 'Firefox'],
customLaunchers: launchers,
concurrency: 1,
Expand All @@ -43,7 +42,8 @@ module.exports = function (config) {
client: {
mocha: {
reporter: 'html',
timeout: 90000
timeout: 40000
// timeout: 2000 - this is the default, see https://mochajs.org/#-timeout-ms-t-ms
}
}
};
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"pushTaggedRelease": "git push --follow-tags --no-verify origin master",
"release": "standard-version",
"test": "NODE_ENV=test karma start --color --mode development",
"test:watch": "NODE_ENV=test karma start --browsers=Chrome --single-run=false --auto-watch",
"watch": "webpack --progress --colors --watch --mode development"
},
"husky": {
Expand Down
94 changes: 62 additions & 32 deletions src/hls-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
AudioTrack,
BaseMediaSourceAdapter,
Env,
Error,
Error as PKError,
EventType,
TextTrack,
Track,
Expand Down Expand Up @@ -98,6 +98,14 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
*/
_loadPromise: ?Promise<Object>;

/**
* the _loadPromise handlers
* @member {{resolve: (result: Promise<R> | R) => void, reject: (error: any) => void}} - _loadPromiseHandlers
* @type {{resolve: (result: Promise<R> | R) => void, reject: (error: any) => void}}
* @private
*/
_loadPromiseHandlers: {resolve: (result: Promise<*> | *) => void, reject: (error: any) => void} | null;

/**
* Reference to the player tracks.
* @member {Array<Track>} - _playerTracks
Expand All @@ -123,7 +131,7 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
_mediaAttachedPromise: Promise<*>;
_requestFilterError: boolean = false;
_responseFilterError: boolean = false;
_nativeTextTracksMap = [];
_nativeTextTracksMap = {};
_lastLoadedFragSN: number = -1;
_sameFragSNLoadedCount: number = 0;
/**
Expand Down Expand Up @@ -492,6 +500,11 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
this._config.hlsConfig.startPosition = this.currentTime;
}
this._reset();

this._loadPromiseHandlers?.reject(
new PKError(PKError.Severity.CRITICAL, PKError.Category.PLAYER, PKError.Code.HLS_FATAL_MEDIA_ERROR, 'media detached while loading')
);
this._loadPromiseHandlers = null;
this._loadPromise = null;
this._hls = null;
}
Expand Down Expand Up @@ -525,8 +538,8 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
load(startTime: ?number): Promise<Object> {
if (!this._loadPromise) {
this._startTime = startTime;
this._loadPromise = new Promise(resolve => {
this._resolveLoad = resolve;
this._loadPromise = new Promise((resolve, reject) => {
this._loadPromiseHandlers = {resolve, reject};
this._loadInternal();
});
}
Expand All @@ -544,6 +557,10 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
this._hls.loadSource(this._sourceObj.url);
this._hls.attachMedia(this._videoElement);
this._trigger(EventType.ABR_MODE_CHANGED, {mode: this.isAdaptiveBitrateEnabled() ? 'auto' : 'manual'});
} else {
this._loadPromiseHandlers?.reject(
new PKError(PKError.Severity.CRITICAL, PKError.Category.PLAYER, PKError.Code.HLS_FATAL_MEDIA_ERROR, 'no url provided')
);
}
}

Expand Down Expand Up @@ -576,15 +593,24 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
super.destroy().then(
() => {
HlsAdapter._logger.debug('destroy');
this._loadPromise = null;
this._playerTracks = [];
this._nativeTextTracksMap = [];
this._nativeTextTracksMap = {};
this._sameFragSNLoadedCount = 0;
this._lastLoadedFragSN = -1;
this._loadPromiseHandlers?.reject(
new PKError(
PKError.Severity.CRITICAL,
PKError.Category.PLAYER,
PKError.Code.HLS_FATAL_MEDIA_ERROR,
'The adapter has been destroyed while loading'
)
);
this._loadPromiseHandlers = null;
this._loadPromise = null;
this._reset();
resolve();
},
() => reject
() => reject()
);
});
}
Expand Down Expand Up @@ -667,15 +693,14 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
*/
_parseTextTracks(hlsTextTracks: Array<Object>): Array<TextTrack> {
let textTracks = [];
for (let i = 0; i < hlsTextTracks.length; i++) {
for (const hlsTextTrack of hlsTextTracks) {
// Create text tracks
let settings = {
id: hlsTextTracks[i].id,
active: hlsTextTracks[i].default,
label: hlsTextTracks[i].name,
kind: hlsTextTracks[i].type.toLowerCase(),
language: hlsTextTracks[i].lang,
index: i
id: hlsTextTrack.id,
active: hlsTextTrack.default,
label: hlsTextTrack.name,
kind: hlsTextTrack.type.toLowerCase(),
language: hlsTextTrack.lang
};
textTracks.push(new TextTrack(settings));
}
Expand All @@ -696,11 +721,10 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
active: CEATextTrack.mode === 'showing',
label: CEATextTrack.label,
kind: CEATextTrack.kind,
language: CEATextTrack.language,
index: this._playerTracks.filter(track => track instanceof TextTrack).length
language: CEATextTrack.language
};
textTrack = new TextTrack(settings);
this._nativeTextTracksMap[settings.index] = CEATextTrack;
this._nativeTextTracksMap[textTrack.index] = CEATextTrack;
}
return textTrack;
}
Expand Down Expand Up @@ -928,7 +952,8 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
this._hls.currentLevel = 0;
}
this._mediaAttachedPromise.then(() => {
this._resolveLoad({tracks: this._playerTracks});
this._loadPromiseHandlers?.resolve({tracks: this._playerTracks});
this._loadPromiseHandlers = null;
});
const {loading} = data.stats;
const manifestDownloadTime = loading.end - loading.start;
Expand Down Expand Up @@ -1080,17 +1105,17 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
const errorFatal = data.fatal;
let errorDataObject = this._getErrorDataObject(data);
if (errorFatal) {
let error: typeof Error;
let error: typeof PKError;
switch (errorType) {
case Hlsjs.ErrorTypes.NETWORK_ERROR:
{
let code;
if (this._requestFilterError) {
code = Error.Code.REQUEST_FILTER_ERROR;
code = PKError.Code.REQUEST_FILTER_ERROR;
} else if (this._responseFilterError) {
code = Error.Code.RESPONSE_FILTER_ERROR;
code = PKError.Code.RESPONSE_FILTER_ERROR;
} else {
code = Error.Code.HTTP_ERROR;
code = PKError.Code.HTTP_ERROR;
}
if (
[Hlsjs.ErrorDetails.MANIFEST_LOAD_ERROR, Hlsjs.ErrorDetails.MANIFEST_LOAD_TIMEOUT].includes(errorName) &&
Expand All @@ -1099,37 +1124,42 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
!this._requestFilterError &&
!this._responseFilterError
) {
error = new Error(Error.Severity.RECOVERABLE, Error.Category.NETWORK, code, errorDataObject);
error = new PKError(PKError.Severity.RECOVERABLE, PKError.Category.NETWORK, code, errorDataObject);
this._reloadWithDirectManifest();
} else {
error = new Error(Error.Severity.CRITICAL, Error.Category.NETWORK, code, errorDataObject);
error = new PKError(PKError.Severity.CRITICAL, PKError.Category.NETWORK, code, errorDataObject);
}
}
break;
case Hlsjs.ErrorTypes.MEDIA_ERROR:
if (this._handleMediaError()) {
error = new Error(Error.Severity.RECOVERABLE, Error.Category.MEDIA, Error.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
error = new PKError(PKError.Severity.RECOVERABLE, PKError.Category.MEDIA, PKError.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
} else {
error = new Error(Error.Severity.CRITICAL, Error.Category.MEDIA, Error.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
error = new PKError(PKError.Severity.CRITICAL, PKError.Category.MEDIA, PKError.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
}
break;
default:
error = new Error(Error.Severity.CRITICAL, Error.Category.PLAYER, Error.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
error = new PKError(PKError.Severity.CRITICAL, PKError.Category.PLAYER, PKError.Code.HLS_FATAL_MEDIA_ERROR, errorDataObject);
break;
}
this._trigger(EventType.ERROR, error);
if (error && error.severity === Error.Severity.CRITICAL) {
if (error && error.severity === PKError.Severity.CRITICAL) {
if (this._loadPromiseHandlers) {
this._loadPromiseHandlers?.reject(error);
this._loadPromiseHandlers = null;
this._loadPromise = null;
}
this.destroy();
}
} else {
const {category, code}: ErrorDetailsType =
this._requestFilterError || this._responseFilterError
? {
category: Error.Category.NETWORK,
code: this._requestFilterError ? Error.Code.REQUEST_FILTER_ERROR : Error.Code.RESPONSE_FILTER_ERROR
category: PKError.Category.NETWORK,
code: this._requestFilterError ? PKError.Code.REQUEST_FILTER_ERROR : PKError.Code.RESPONSE_FILTER_ERROR
}
: HlsJsErrorMap[errorName] || {category: 0, code: 0};
HlsAdapter._logger.warn(new Error(Error.Severity.RECOVERABLE, category, code, errorDataObject));
HlsAdapter._logger.warn(new PKError(PKError.Severity.RECOVERABLE, category, code, errorDataObject));
}
this._requestFilterError = false;
this._responseFilterError = false;
Expand Down Expand Up @@ -1265,7 +1295,7 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
HlsAdapter._logger.debug(`Same frag SN. Count is: ${this._sameFragSNLoadedCount}, Max is: ${this._config.network.maxStaleLevelReloads}`);
if (this._sameFragSNLoadedCount >= this._config.network.maxStaleLevelReloads) {
HlsAdapter._logger.error(`Same frag loading reached max count`);
const error = new Error(Error.Severity.CRITICAL, Error.Category.NETWORK, Error.Code.LIVE_MANIFEST_REFRESH_ERROR, {
const error = new PKError(PKError.Severity.CRITICAL, PKError.Category.NETWORK, PKError.Code.LIVE_MANIFEST_REFRESH_ERROR, {
fragSN: endSN
});
this._trigger(EventType.ERROR, error);
Expand Down
Loading

0 comments on commit 12091d4

Please sign in to comment.