Skip to content

Commit

Permalink
Fallback to target SN if PDT is missing in live start frag look up
Browse files Browse the repository at this point in the history
Do not set previous segment to "initSegment" as a sequence number is expected
Fix demo timeline setup and updates of LL-HLS streams with query params
video-dev#3473
  • Loading branch information
Rob Walch committed Feb 22, 2021
1 parent 874fc7a commit 8687cf1
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 13 deletions.
19 changes: 15 additions & 4 deletions demo/chart/timeline-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,11 @@ export class TimelineChart {
updateLevelOrTrack(details: LevelDetails) {
const { targetduration, totalduration, url } = details;
const { datasets } = this.chart.data;
// eslint-disable-next-line no-restricted-properties
const deliveryDirectivePattern = /[?&]_HLS_(?:msn|part|skip)=[^?&]+/g;
const levelDataSet = arrayFind(
datasets,
(dataset) =>
dataset.url?.toString().replace(deliveryDirectivePattern, '') ===
url.replace(deliveryDirectivePattern, '')
stripDeliveryDirectives(url) ===
stripDeliveryDirectives(dataset.url || '')
);
if (!levelDataSet) {
return;
Expand Down Expand Up @@ -659,6 +657,19 @@ export class TimelineChart {
}
}

function stripDeliveryDirectives(url: string): string {
try {
const webUrl: URL = new self.URL(url);
webUrl.searchParams.delete('_HLS_msn');
webUrl.searchParams.delete('_HLS_part');
webUrl.searchParams.delete('_HLS_skip');
webUrl.searchParams.sort();
return webUrl.href;
} catch (e) {
return url.replace(/[?&]_HLS_(?:msn|part|skip)=[^?&]+/g, '');
}
}

function datasetWithDefaults(options) {
return Object.assign(
{
Expand Down
2 changes: 1 addition & 1 deletion demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1583,7 +1583,7 @@ function addChartEventListeners(hls) {
chart
);
hls.on(
Hls.Events.MANIFEST_LOADED,
Hls.Events.MANIFEST_PARSED,
(eventName, data) => {
const { levels } = data;
chart.removeType('level');
Expand Down
10 changes: 6 additions & 4 deletions src/controller/audio-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,10 +590,12 @@ class AudioStreamController
);
return;
}
this.fragPrevious = frag;
if (this.audioSwitch && frag.sn !== 'initSegment') {
this.audioSwitch = false;
this.hls.trigger(Events.AUDIO_TRACK_SWITCHED, { id: this.trackId });
if (frag.sn !== 'initSegment') {
this.fragPrevious = frag;
if (this.audioSwitch) {
this.audioSwitch = false;
this.hls.trigger(Events.AUDIO_TRACK_SWITCHED, { id: this.trackId });
}
}
this.fragBufferedComplete(frag, part);
}
Expand Down
3 changes: 2 additions & 1 deletion src/controller/base-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,8 @@ export default class BaseStreamController
fragPrevious.endProgramDateTime,
config.maxFragLookUpTolerance
);
} else {
}
if (!frag) {
// SN does not need to be accurate between renditions, but depending on the packaging it may be so.
const targetSN = (fragPrevious.sn as number) + 1;
if (
Expand Down
16 changes: 13 additions & 3 deletions src/controller/stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,9 @@ export default class StreamController
this.fragLastKbps = Math.round(
(8 * stats.total) / (stats.buffering.end - stats.loading.first)
);
this.fragPrevious = frag;
if (frag.sn !== 'initSegment') {
this.fragPrevious = frag;
}
this.fragBufferedComplete(frag, part);
}

Expand Down Expand Up @@ -876,15 +878,23 @@ export default class StreamController
);
// @ts-ignore - frag is potentially null according to TS here
this.warn(
`Fragment ${frag?.sn} of level ${frag?.level} failed to load, retrying in ${delay}ms`
`Fragment ${frag.sn} of level ${frag.level} failed to load, retrying in ${delay}ms`
);
this.retryDate = self.performance.now() + delay;
// retry loading state
// if loadedmetadata is not set, it means that we are emergency switch down on first frag
// in that case, reset startFragRequested flag
if (!this.loadedmetadata) {
this.startFragRequested = false;
this.nextLoadPosition = this.startPosition;
const details = this.levels
? this.levels[frag.level].details
: null;
if (details?.live) {
this.startPosition = -1;
this.setStartPosition(details, 0);
} else {
this.nextLoadPosition = this.startPosition;
}
}
this.fragLoadError++;
this.state = State.FRAG_LOADING_WAITING_RETRY;
Expand Down
1 change: 1 addition & 0 deletions src/loader/m3u8-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export default class M3U8Parser {
totalduration -= prevFrag.duration;
level.fragmentHint = prevFrag;
} else {
assignProgramDateTime(frag, prevFrag);
level.fragmentHint = frag;
}
const fragmentLength = fragments.length;
Expand Down

0 comments on commit 8687cf1

Please sign in to comment.