Skip to content

Commit

Permalink
Merge branch 'feature/v1.0.0' into LHLS
Browse files Browse the repository at this point in the history
* feature/v1.0.0:
  Remove change in tsdemuxer that caused video tearing Fixes video-dev#2514
  fix: remove uneeded tests
  remove computeLive test
  Update base-stream-controller.js
  Fix issue in TS Demuxer that skipped AAC frames at the end of PES packets Fixes video-dev#2528
  Update dependencies and package-lock
  Fix formatting of example
  Remove stats assert since loader resets stats
  Use fragment stats in loaders and reset stats on load
  fix: computeLivePosition minimum value of media.currentTime
  trigger ci
  remove .only
  load audio playlist on MANIFEST_PARSED
  tsdemuxer: if PES does not contain PTS/DTS, use last PES PTS/DTS instead
  • Loading branch information
Rob Walch committed Feb 27, 2020
2 parents 466d98e + 43e57ca commit 37a7b5e
Show file tree
Hide file tree
Showing 14 changed files with 12,028 additions and 10,776 deletions.
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -63,11 +63,11 @@ Find the commit on [https://github.com/video-dev/hls.js/blob/deployments/README.
<video id="video"></video>
<script>
var video = document.getElementById('video');
if(Hls.isSupported()) {
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
}
Expand All @@ -78,7 +78,7 @@ Find the commit on [https://github.com/video-dev/hls.js/blob/deployments/README.
// white-list before a 'canplay' event will be emitted; the last video event that can be reliably listened-for when the URL is not on the white-list is 'loadedmetadata'.
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8';
video.addEventListener('loadedmetadata',function() {
video.addEventListener('loadedmetadata', function() {
video.play();
});
}
Expand Down
22,679 changes: 11,941 additions & 10,738 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions package.json
Expand Up @@ -69,35 +69,35 @@
"babel-loader": "8.0.4",
"babel-plugin-transform-remove-console": "6.9.4",
"chai": "4.2.0",
"chromedriver": "^79.0.0",
"chromedriver": "^80.0.1",
"eslint": "^6.4.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-mocha": "^6.1.1",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"http-server": "^0.11.0",
"http-server": "^0.12.1",
"husky": "^3.0.7",
"istanbul-instrumenter-loader": "^3.0.1",
"karma": "4.1.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage-istanbul-reporter": "2.0.4",
"karma": "^4.4.1",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^2.1.1",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.5",
"karma-sinon-chai": "^2.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^3.0.5",
"karma-webpack": "^4.0.2",
"mocha": "^5.2.0",
"netlify-cli": "^2.5.1",
"netlify-cli": "^2.36.0",
"selenium-webdriver": "^3.1.0",
"sinon": "7.1.1",
"sinon-chai": "3.3.0",
"typescript": "^3.7.4",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.4",
"webpack-merge": "^4.2.1",
"webpack-merge": "^4.2.2",
"webworkify-webpack": "^2.1.5"
}
}
8 changes: 6 additions & 2 deletions src/controller/audio-track-controller.ts
Expand Up @@ -193,9 +193,13 @@ class AudioTrackController implements NetworkComponentAPI {
* selected one (based on NAME property).
*/
protected onLevelLoading (event: Events.LEVEL_LOADING, data: LevelLoadingData): void {
const levelInfo = this.hls.levels[data.level];
this._selectAudioGroup(data.level);
}

private _selectAudioGroup (levelId: number) {
const levelInfo = this.hls.levels[levelId];

if (!levelInfo.audioGroupIds) {
if (!levelInfo?.audioGroupIds) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/controller/base-stream-controller.ts
Expand Up @@ -501,7 +501,7 @@ export default class BaseStreamController extends TaskLoop {
const liveSyncPosition = this._liveSyncPosition = this.computeLivePosition(start, targetDuration, totalDuration);
this.log(`Buffer end: ${bufferEnd.toFixed(3)} is located too far from the end of live sliding playlist, reset currentTime to : ${liveSyncPosition.toFixed(3)}`);
this.nextLoadPosition = liveSyncPosition;
if (media?.readyState && media.duration > liveSyncPosition) {
if (media?.readyState && media.duration > liveSyncPosition && liveSyncPosition > media.currentTime) {
media.currentTime = liveSyncPosition;
}
return liveSyncPosition;
Expand Down
27 changes: 13 additions & 14 deletions src/demux/tsdemuxer.ts
Expand Up @@ -335,15 +335,12 @@ class TSDemuxer implements Demuxer {
audioTrack.pesData = audioData;
id3Track.pesData = id3Data;

const result = {
return {
audioTrack,
avcTrack,
id3Track,
textTrack: this._txtTrack
};

this.extractRemainingSamples(result);
return result;
}

flush () {
Expand Down Expand Up @@ -945,17 +942,19 @@ class TSDemuxer implements Demuxer {

// scan for aac samples
while (offset < len) {
if (ADTS.isHeader(data, offset) && (offset + 5) < len) {
const frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
// logger.log(`${Math.round(frame.sample.pts)} : AAC`);
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
} else {
// logger.log('Unable to parse AAC frame');
break;
if (ADTS.isHeader(data, offset)) {
if ((offset + 5) < len) {
const frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
continue;
}
}
// We are at an ADTS header, but do not have enough data for a frame
// Remaining data will be added to aacOverFlow
break;
} else {
// nothing found, keep looking
offset++;
Expand Down
4 changes: 1 addition & 3 deletions src/loader/fragment-loader.ts
Expand Up @@ -112,9 +112,7 @@ export default class FragmentLoader {
}
};
// Assign frag stats to the loader's stats reference
frag.stats = loader.stats;
// Loaders are used once per fragment and should be reset at this point
console.assert(!frag.stats.loading.start, 'Frag stats should be unset before loading');
loader.stats = frag.stats;
loader.load(loaderContext, loaderConfig, callbacks);
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/loader/level-details.ts
Expand Up @@ -20,7 +20,7 @@ export default class LevelDetails {
public tload?: number;
public totalduration: number = 0;
public type: string | null = null;
public updated?: boolean; // Manifest reload synchronization
public updated: boolean = true;
public misses: number = 0;
public url: string;
public version: number | null = null;
Expand Down
10 changes: 10 additions & 0 deletions src/loader/load-stats.ts
Expand Up @@ -11,3 +11,13 @@ export default class LoadStats implements LoaderStats {
parsing: HlsPerformanceTiming = { start: 0, end: 0 };
buffering: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };
}

export function reset (stats: LoaderStats) {
stats.loading = { start: 0, first: 0, end: 0 };
stats.parsing = { start: 0, end: 0 };
stats.buffering = { start: 0, first: 0, end: 0 };
stats.loaded = 0;
stats.aborted = false;
stats.retry = 0;
stats.chunkCount = 0;
}
2 changes: 1 addition & 1 deletion src/loader/m3u8-parser.ts
Expand Up @@ -146,7 +146,7 @@ export default class M3U8Parser {
return medias;
}

static parseLevelPlaylist (string: string, baseurl: string, id: number, type: PlaylistLevelType, levelUrlId: number) {
static parseLevelPlaylist (string: string, baseurl: string, id: number, type: PlaylistLevelType, levelUrlId: number): LevelDetails {
let currentSN = 0;
let totalduration = 0;
const level = new LevelDetails(baseurl);
Expand Down
6 changes: 3 additions & 3 deletions src/types/events.ts
Expand Up @@ -136,7 +136,7 @@ export interface AudioTrackLoadingData {
}

export interface AudioTrackLoadedData {
details: any; // LevelDetails type?
details: LevelDetails;
id: number;
stats: LoaderStats;
networkDetails: unknown;
Expand All @@ -160,7 +160,7 @@ export interface SubtitleTrackLoadingData {
}

export interface SubtitleTrackLoadedData {
details: any; // LevelDetails type?
details: LevelDetails;
id: number | null;
stats: LoaderStats;
networkDetails: unknown;
Expand All @@ -176,7 +176,7 @@ export interface SubtitleFragProcessed {
}

export interface FragChangedData {
frag: any;
frag: Fragment;
}

export interface FPSDropData {
Expand Down
3 changes: 2 additions & 1 deletion src/utils/fetch-loader.ts
Expand Up @@ -6,7 +6,7 @@ import {
LoaderConfiguration,
LoaderOnProgress
} from '../types/loader';
import LoadStats from '../loader/load-stats';
import LoadStats, { reset } from '../loader/load-stats';
import ChunkCache from '../demux/chunk-cache';

const { fetch, AbortController, ReadableStream, Request, Headers, performance } = self;
Expand Down Expand Up @@ -56,6 +56,7 @@ class FetchLoader implements Loader<LoaderContext> {

load (context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>): void {
const stats = this.stats;
reset(stats);
stats.loading.start = performance.now();

const initParams = getRequestParameters(context, this.controller.signal);
Expand Down
3 changes: 2 additions & 1 deletion src/utils/xhr-loader.ts
@@ -1,6 +1,6 @@
import { logger } from '../utils/logger';
import { LoaderCallbacks, LoaderContext, LoaderStats, Loader, LoaderConfiguration } from '../types/loader';
import LoadStats from '../loader/load-stats';
import LoadStats, { reset } from '../loader/load-stats';

class XhrLoader implements Loader<LoaderContext> {
private xhrSetup: Function | null;
Expand Down Expand Up @@ -49,6 +49,7 @@ class XhrLoader implements Loader<LoaderContext> {
this.context = context;
this.config = config;
this.callbacks = callbacks;
reset(this.stats);
this.stats.loading.start = performance.now();
this.retryDelay = config.retryDelay;
this.loadInternal();
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/controller/audio-track-controller.js
Expand Up @@ -81,6 +81,42 @@ describe('AudioTrackController', function () {
});
});

it('should select audioGroupId and trigger AUDIO_TRACK_SWITCHING', function (done) {
hls.on(Hls.Events.AUDIO_TRACK_SWITCHING, (event, data) => {
done();
});

const levels = [
{
urlId: 1,
audioGroupIds: ['1', '2']
}
];

hls.levelController = {
levels
};

const newLevelInfo = levels[0];
const newGroupId = newLevelInfo.audioGroupIds[newLevelInfo.urlId];

audioTrackController.audioGroupId = '1';
audioTrackController.tracks = tracks;
audioTrackController.audioTrack = 2;

// current track name
const audioTrackName = tracks[audioTrackController.audioTrack].name;

audioTrackController.onManifestParsed({
audioTracks: tracks
});

// group has switched
expect(audioTrackController.audioGroupId).to.equal(newGroupId);
// name is still the same
expect(tracks[audioTrackController.audioTrack].name).to.equal(audioTrackName);
});

describe('_needsTrackLoading', function () {
it('should not need loading because the audioTrack is embedded in the main playlist', function () {
expect(audioTrackController._needsTrackLoading({ details: { live: true } })).to.be.false;
Expand Down

0 comments on commit 37a7b5e

Please sign in to comment.