Skip to content

Commit

Permalink
Merge pull request #3705 from video-dev/task/readme-and-func-test-fixes
Browse files Browse the repository at this point in the history
IE11, README v1, and Functional Test Fixes
  • Loading branch information
robwalch committed Apr 1, 2021
2 parents b187a6c + d642557 commit f20e155
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 62 deletions.
20 changes: 10 additions & 10 deletions README.md
Expand Up @@ -59,19 +59,19 @@ Find the commit on [https://github.com/video-dev/hls.js/blob/deployments/README.

hls.js is only compatible with browsers supporting MediaSource extensions (MSE) API with 'video/MP4' mime-type inputs.

Hls.js is supported on:
hls.js is supported on:

- Chrome for Android 39+
- Chrome for Desktop 39+
- Firefox for Android 41+
- Firefox for Desktop 42+
- IE11+ for Windows 8.1+
- Chrome 39+ for Android
- Chrome 39+ for Desktop
- Firefox 41+ for Android
- Firefox 42+ for Desktop
- IE11 for Windows 8.1+
- Edge for Windows 10+
- Opera for Desktop
- Vivaldi for Desktop
- Safari for Mac 8+ (beta)
- Safari 8+ for MacOS 10.10+
- Safari for ipadOS 13+

A [Promise polyfill](https://github.com/taylorhakes/promise-polyfill) is required in browsers missing native promise support.

**Please note:** iOS Safari on iPhone does not support the MediaSource API. This includes all browsers on iOS as well as apps using UIWebView and WKWebView.

Safari browsers (iOS, iPadOS, and macOS) have built-in HLS support through the plain video "tag" source URL. See the example below (Getting Started) to run appropriate feature detection and choose between using Hls.js or natively built-in HLS support.
Expand Down Expand Up @@ -193,7 +193,7 @@ made by [gramk](https://github.com/gramk/chrome-hls), plays hls from address bar
No external JS libs are needed.
Prepackaged builds are included [with each release](https://github.com/video-dev/hls.js/releases).

Hls.js can be installed as a dependency using npm:
hls.js can be installed as a dependency using npm:

```
npm install hls.js
Expand Down
1 change: 1 addition & 0 deletions api-extractor/report/hls.js.api.md
Expand Up @@ -841,6 +841,7 @@ class Hls implements HlsEventEmitter {
static set DefaultConfig(defaultConfig: HlsConfig);
destroy(): void;
detachMedia(): void;
get drift(): number | null;
// (undocumented)
emit<E extends keyof HlsListeners>(event: E, name: E, eventObject: Parameters<HlsListeners[E]>[1]): boolean;
// (undocumented)
Expand Down
4 changes: 2 additions & 2 deletions demo/chart/timeline-chart.ts
Expand Up @@ -435,7 +435,7 @@ export class TimelineChart {
sourceBuffer,
})
);
sourceBuffer.onupdate = () => {
sourceBuffer.addEventListener('update', () => {
try {
replaceTimeRangeTuples(sourceBuffer.buffered, data);
} catch (error) {
Expand All @@ -445,7 +445,7 @@ export class TimelineChart {
}
replaceTimeRangeTuples(media.buffered, mediaBufferData);
this.update();
};
});
});

if (trackTypes.length === 0) {
Expand Down
4 changes: 1 addition & 3 deletions demo/main.js
Expand Up @@ -1215,9 +1215,7 @@ function checkBuffer() {
` Max Latency: ${hls.maxLatency}\n` +
` Target Latency: ${hls.targetLatency.toFixed(3)}\n` +
` Latency: ${hls.latency.toFixed(3)}\n` +
` Drift: ${hls.latencyController.drift.toFixed(
3
)} (edge advance rate)\n` +
` Drift: ${hls.drift.toFixed(3)} (edge advance rate)\n` +
` Edge Stall: ${hls.latencyController.edgeStalled.toFixed(
3
)} (playlist refresh over target duration/part)\n` +
Expand Down
6 changes: 5 additions & 1 deletion docs/API.md
@@ -1,4 +1,4 @@
# API
# HLS.js v1 API

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
Expand Down Expand Up @@ -1347,6 +1347,10 @@ returns 0 before first playlist is loaded

get : target distance from the edge as calculated by the latency controller

### `hls.drift`

get : the rate at which the edge of the current live playlist is advancing or 1 if there is none

## Runtime Events

hls.js fires a bunch of events, that could be registered and unregistered as below:
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -49,6 +49,7 @@
"test:func": "BABEL_ENV=development mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
"test:func:light": "BABEL_ENV=development HLSJS_LIGHT=1 mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
"test:func:sauce": "SAUCE=1 UA=safari OS='OS X 10.15' BABEL_ENV=development mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
"test:func:sauce-ie": "SAUCE=1 UA='internet explorer' OS='Windows 10' BABEL_ENV=development mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch"
},
Expand Down
6 changes: 4 additions & 2 deletions src/controller/base-stream-controller.ts
Expand Up @@ -312,10 +312,12 @@ export default class BaseStreamController
return;
}
this.fragLoadError = 0;
const state = this.state;
if (this.fragContextChanged(frag)) {
if (
this.state === State.FRAG_LOADING ||
this.state === State.BACKTRACKING
state === State.FRAG_LOADING ||
state === State.BACKTRACKING ||
(!this.fragCurrent && state === State.PARSING)
) {
this.fragmentTracker.removeFragment(frag);
this.state = State.IDLE;
Expand Down
2 changes: 1 addition & 1 deletion src/controller/buffer-controller.ts
Expand Up @@ -398,7 +398,7 @@ export default class BufferController implements ComponentAPI {
browser is able to evict some data from sourcebuffer. Retrying can help recover.
*/
if (this.appendError > hls.config.appendErrorMaxRetry) {
logger.log(
logger.error(
`[buffer-controller]: Failed ${hls.config.appendErrorMaxRetry} times to append segment in sourceBuffer`
);
event.fatal = true;
Expand Down
2 changes: 1 addition & 1 deletion src/controller/stream-controller.ts
Expand Up @@ -470,11 +470,11 @@ export default class StreamController

private abortCurrentFrag() {
const fragCurrent = this.fragCurrent;
this.fragCurrent = null;
if (fragCurrent?.loader) {
fragCurrent.loader.abort();
}
this.nextLoadPosition = this.getLoadPosition();
this.fragCurrent = null;
}

protected flushMainBuffer(startOffset: number, endOffset: number) {
Expand Down
8 changes: 8 additions & 0 deletions src/hls.ts
Expand Up @@ -789,6 +789,14 @@ export default class Hls implements HlsEventEmitter {
return this.latencyController.targetLatency;
}

/**
* the rate at which the edge of the current live playlist is advancing or 1 if there is none
* @type {number}
*/
get drift(): number | null {
return this.latencyController.drift;
}

/**
* set to true when startLoad is called before MANIFEST_PARSED event
* @type {boolean}
Expand Down
38 changes: 38 additions & 0 deletions tests/functional/auto/.eslintrc.js
@@ -0,0 +1,38 @@
module.exports = {
env: {
node: true,
commonjs: true,
es6: false,
mocha: true,
},
plugins: ['mocha', 'node'],
globals: {
// Test globals
after: false,
afterEach: false,
assert: false,
before: false,
beforeEach: false,
describe: false,
expect: true,
sinon: false,
xit: false,
},
rules: {
'object-shorthand': ['error', 'never'], // Object-shorthand not supported in IE11
// destructuring is not supported in IE11. This does not prevent it.
// ES6 env settings in parent files cannot be overwritten.
'prefer-destructuring': ['error', { object: false, array: false }],
'one-var': 0,
'no-undefined': 0,
'no-unused-expressions': 0,
'no-restricted-properties': [
2,
{ property: 'findIndex' }, // Intended to block usage of Array.prototype.findIndex
{ property: 'find' }, // Intended to block usage of Array.prototype.find
{ property: 'only' }, // Intended to block usage of it.only in commits
],
'node/no-restricted-require': ['error', ['assert']],
'mocha/no-mocha-arrows': 2,
},
};
1 change: 1 addition & 0 deletions tests/functional/auto/index-light.html
@@ -1,6 +1,7 @@
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="../../../node_modules/promise-polyfill/dist/polyfill.min.js"></script>
<script src="../../../dist/hls.light.min.js"></script>
<script src="testbench.js"></script>
</head>
Expand Down
1 change: 1 addition & 0 deletions tests/functional/auto/index.html
@@ -1,6 +1,7 @@
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="../../../node_modules/promise-polyfill/dist/polyfill.min.js"></script>
<script src="../../../dist/hls.min.js"></script>
<script src="testbench.js"></script>
</head>
Expand Down
47 changes: 23 additions & 24 deletions tests/functional/auto/setup.js
Expand Up @@ -151,13 +151,10 @@ async function testSmoothSwitch(url, config) {
const result = await browser.executeAsyncScript(
function (url, config) {
const callback = arguments[arguments.length - 1];
self.startStream(
url,
self.objectAssign(config, {
startLevel: 0,
}),
callback
);
const startConfig = self.objectAssign(config, {
startLevel: 0,
});
self.startStream(url, startConfig, callback);
self.hls.manualLevel = 0;
const video = self.video;
self.hls.once(self.Hls.Events.FRAG_CHANGED, function (eventName, data) {
Expand All @@ -167,7 +164,7 @@ async function testSmoothSwitch(url, config) {
const highestLevel = self.hls.levels.length - 1;
if (highestLevel === 0) {
callback({
highestLevel,
highestLevel: highestLevel,
currentTimeDelta: 0,
message: 'No adaptive variants',
logs: self.logString,
Expand All @@ -188,9 +185,9 @@ async function testSmoothSwitch(url, config) {
'[test] > currentTime delta: ' + (newCurrentTime - currentTime)
);
callback({
highestLevel,
highestLevel: highestLevel,
currentTimeDelta: newCurrentTime - currentTime,
paused,
paused: paused,
logs: self.logString,
});
}, 2000);
Expand Down Expand Up @@ -249,21 +246,22 @@ async function testSeekOnVOD(url, config) {
if (!isFinite(duration)) {
callback({
code: 'non-finite-duration',
duration,
duration: duration,
logs: self.logString,
});
}
// After seeking timeout if paused after 5 seconds
video.onseeked = function () {
console.log('[test] > video "onseeked"');
self.setTimeout(function () {
const { currentTime, paused } = video;
if (currentTime === 0 || paused) {
const currentTime = video.currentTime;
const paused = video.paused;
if (video.currentTime === 0 || paused) {
callback({
code: 'paused',
currentTime,
duration,
paused,
currentTime: currentTime,
duration: duration,
paused: paused,
logs: self.logString,
});
}
Expand All @@ -278,12 +276,13 @@ async function testSeekOnVOD(url, config) {
);
video.currentTime = seekToTime;
self.setTimeout(function () {
const { currentTime, paused } = video;
const currentTime = video.currentTime;
const paused = video.paused;
callback({
code: 'timeout-waiting-for-ended-event',
currentTime,
duration,
paused,
currentTime: currentTime,
duration: duration,
paused: paused,
logs: self.logString,
});
}, 12000);
Expand All @@ -297,7 +296,7 @@ async function testSeekOnVOD(url, config) {
callback({
code: 'buffer-gaps',
bufferedRanges: video.buffered.length,
duration,
duration: duration,
logs: self.logString,
});
}
Expand Down Expand Up @@ -420,7 +419,7 @@ async function sauceConnect(tunnelIdentifier) {
);
sauceConnectLauncher(
{
tunnelIdentifier,
tunnelIdentifier: tunnelIdentifier,
},
(err, sauceConnectProcess) => {
if (err) {
Expand Down Expand Up @@ -590,8 +589,8 @@ describe(`testing hls.js playback in the browser on "${browserDescription}"`, fu
const url = stream.url;
const config = stream.config || {};
if (
stream.blacklist_ua &&
stream.blacklist_ua.some((browserInfo) => {
stream.skip_ua &&
stream.skip_ua.some((browserInfo) => {
if (typeof browserInfo === 'string') {
return browserInfo === browserConfig.name;
}
Expand Down

0 comments on commit f20e155

Please sign in to comment.