hls.js 1.6.3-0.canary.11253 → 1.6.3-0.canary.11254
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hls.d.mts +3 -3
- package/dist/hls.d.ts +3 -3
- package/dist/hls.js +59 -56
- package/dist/hls.js.d.ts +3 -3
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +34 -15
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +36 -15
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +62 -59
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/audio-stream-controller.ts +39 -31
- package/src/controller/base-stream-controller.ts +8 -4
- package/src/controller/fragment-finders.ts +18 -14
- package/src/controller/interstitials-controller.ts +1 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
import BaseStreamController, { State } from './base-stream-controller';
|
2
|
-
import {
|
2
|
+
import { findNearestWithCC } from './fragment-finders';
|
3
3
|
import { FragmentState } from './fragment-tracker';
|
4
4
|
import ChunkCache from '../demux/chunk-cache';
|
5
5
|
import TransmuxerInterface from '../demux/transmuxer-interface';
|
@@ -161,32 +161,56 @@ class AudioStreamController
|
|
161
161
|
(!waitingData && !this.loadingParts) ||
|
162
162
|
(waitingData && waitingData.frag.cc !== cc)
|
163
163
|
) {
|
164
|
-
this.
|
164
|
+
this.syncWithAnchor(frag, waitingData?.frag);
|
165
165
|
}
|
166
|
-
this.tick();
|
167
166
|
} else if (
|
168
167
|
!this.hls.hasEnoughToStart &&
|
169
168
|
inFlightFrag &&
|
170
169
|
inFlightFrag.cc !== cc
|
171
170
|
) {
|
172
|
-
this.startFragRequested = false;
|
173
|
-
this.nextLoadPosition = this.findSyncFrag(frag).start;
|
174
171
|
inFlightFrag.abortRequests();
|
175
|
-
this.
|
172
|
+
this.syncWithAnchor(frag, inFlightFrag);
|
176
173
|
} else if (this.state === State.IDLE) {
|
177
174
|
this.tick();
|
178
175
|
}
|
179
176
|
}
|
180
177
|
}
|
181
178
|
|
182
|
-
|
179
|
+
protected getLoadPosition(): number {
|
180
|
+
if (!this.startFragRequested && this.nextLoadPosition >= 0) {
|
181
|
+
return this.nextLoadPosition;
|
182
|
+
}
|
183
|
+
return super.getLoadPosition();
|
184
|
+
}
|
185
|
+
|
186
|
+
private syncWithAnchor(
|
187
|
+
mainAnchor: MediaFragment,
|
188
|
+
waitingToAppend: Fragment | undefined,
|
189
|
+
) {
|
190
|
+
// Drop waiting fragment if videoTrackCC has changed since waitingFragment was set and initPTS was not found
|
191
|
+
const mainFragLoading = this.mainFragLoading?.frag || null;
|
192
|
+
if (waitingToAppend) {
|
193
|
+
if (mainFragLoading?.cc === waitingToAppend.cc) {
|
194
|
+
// Wait for loading frag to complete and INIT_PTS_FOUND
|
195
|
+
return;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
const targetDiscontinuity = (mainFragLoading || mainAnchor).cc;
|
183
199
|
const trackDetails = this.getLevelDetails();
|
184
|
-
const
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
200
|
+
const pos = this.getLoadPosition();
|
201
|
+
const syncFrag = findNearestWithCC(trackDetails, targetDiscontinuity, pos);
|
202
|
+
// Only stop waiting for audioFrag.cc if an audio segment of the same discontinuity domain (cc) is found
|
203
|
+
if (syncFrag) {
|
204
|
+
this.log(
|
205
|
+
`Waiting fragment cc (${waitingToAppend?.cc}) cancelled because video is at cc ${mainAnchor.cc}`,
|
206
|
+
);
|
207
|
+
this.startFragRequested = false;
|
208
|
+
this.nextLoadPosition = syncFrag.start;
|
209
|
+
this.resetLoadingState();
|
210
|
+
if (this.state === State.IDLE) {
|
211
|
+
this.doTickIdle();
|
212
|
+
}
|
213
|
+
}
|
190
214
|
}
|
191
215
|
|
192
216
|
startLoad(startPosition: number, skipSeekToStartPosition?: boolean) {
|
@@ -265,12 +289,7 @@ class AudioStreamController
|
|
265
289
|
super._handleFragmentLoadComplete(data);
|
266
290
|
}
|
267
291
|
} else if (mainAnchor && mainAnchor.cc !== waitingData.frag.cc) {
|
268
|
-
|
269
|
-
this.log(
|
270
|
-
`Waiting fragment cc (${frag.cc}) cancelled because video is at cc ${mainAnchor.cc}`,
|
271
|
-
);
|
272
|
-
this.nextLoadPosition = this.findSyncFrag(mainAnchor).start;
|
273
|
-
this.clearWaitingFragment();
|
292
|
+
this.syncWithAnchor(mainAnchor, waitingData.frag);
|
274
293
|
}
|
275
294
|
} else {
|
276
295
|
this.state = State.IDLE;
|
@@ -281,23 +300,12 @@ class AudioStreamController
|
|
281
300
|
this.onTickEnd();
|
282
301
|
}
|
283
302
|
|
284
|
-
|
303
|
+
protected resetLoadingState() {
|
285
304
|
const waitingData = this.waitingData;
|
286
305
|
if (waitingData) {
|
287
|
-
if (!this.hls.hasEnoughToStart) {
|
288
|
-
// Load overlapping fragment on start when discontinuity start times are not aligned
|
289
|
-
this.startFragRequested = false;
|
290
|
-
}
|
291
306
|
this.fragmentTracker.removeFragment(waitingData.frag);
|
292
307
|
this.waitingData = null;
|
293
|
-
if (this.state !== State.STOPPED) {
|
294
|
-
this.state = State.IDLE;
|
295
|
-
}
|
296
308
|
}
|
297
|
-
}
|
298
|
-
|
299
|
-
protected resetLoadingState() {
|
300
|
-
this.clearWaitingFragment();
|
301
309
|
super.resetLoadingState();
|
302
310
|
}
|
303
311
|
|
@@ -2,7 +2,7 @@ import { ErrorActionFlags, NetworkErrorAction } from './error-controller';
|
|
2
2
|
import {
|
3
3
|
findFragmentByPDT,
|
4
4
|
findFragmentByPTS,
|
5
|
-
|
5
|
+
findNearestWithCC,
|
6
6
|
} from './fragment-finders';
|
7
7
|
import { FragmentState } from './fragment-tracker';
|
8
8
|
import Decrypter from '../crypt/decrypter';
|
@@ -1298,7 +1298,7 @@ export default class BaseStreamController
|
|
1298
1298
|
this.log(`LL-Part loading ON for initial live fragment`);
|
1299
1299
|
this.loadingParts = true;
|
1300
1300
|
}
|
1301
|
-
frag = this.getInitialLiveFragment(levelDetails
|
1301
|
+
frag = this.getInitialLiveFragment(levelDetails);
|
1302
1302
|
const mainStart = this.hls.startPosition;
|
1303
1303
|
const liveSyncPosition = this.hls.liveSyncPosition;
|
1304
1304
|
const startPosition = frag
|
@@ -1506,8 +1506,8 @@ export default class BaseStreamController
|
|
1506
1506
|
*/
|
1507
1507
|
protected getInitialLiveFragment(
|
1508
1508
|
levelDetails: LevelDetails,
|
1509
|
-
fragments: MediaFragment[],
|
1510
1509
|
): MediaFragment | null {
|
1510
|
+
const fragments = levelDetails.fragments;
|
1511
1511
|
const fragPrevious = this.fragPrevious;
|
1512
1512
|
let frag: MediaFragment | null = null;
|
1513
1513
|
if (fragPrevious) {
|
@@ -1543,7 +1543,11 @@ export default class BaseStreamController
|
|
1543
1543
|
// It's important to stay within the continuity range if available; otherwise the fragments in the playlist
|
1544
1544
|
// will have the wrong start times
|
1545
1545
|
if (!frag) {
|
1546
|
-
frag =
|
1546
|
+
frag = findNearestWithCC(
|
1547
|
+
levelDetails,
|
1548
|
+
fragPrevious.cc,
|
1549
|
+
fragPrevious.end,
|
1550
|
+
);
|
1547
1551
|
if (frag) {
|
1548
1552
|
this.log(
|
1549
1553
|
`Live playlist, switching playlist, load frag with same CC: ${frag.sn}`,
|
@@ -33,7 +33,6 @@ export function findFragmentByPDT(
|
|
33
33
|
return null;
|
34
34
|
}
|
35
35
|
|
36
|
-
maxFragLookUpTolerance = maxFragLookUpTolerance || 0;
|
37
36
|
for (let seg = 0; seg < fragments.length; ++seg) {
|
38
37
|
const frag = fragments[seg];
|
39
38
|
if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) {
|
@@ -225,28 +224,33 @@ export function findFragWithCC(
|
|
225
224
|
export function findNearestWithCC(
|
226
225
|
details: LevelDetails | undefined,
|
227
226
|
cc: number,
|
228
|
-
|
227
|
+
pos: number,
|
229
228
|
): MediaFragment | null {
|
230
229
|
if (details) {
|
231
230
|
if (details.startCC <= cc && details.endCC >= cc) {
|
232
|
-
const start = fragment.start;
|
233
|
-
const end = fragment.end;
|
234
231
|
let fragments = details.fragments;
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
fragments = fragments.concat(fragmentHint);
|
239
|
-
}
|
232
|
+
const { fragmentHint } = details;
|
233
|
+
if (fragmentHint) {
|
234
|
+
fragments = fragments.concat(fragmentHint);
|
240
235
|
}
|
241
|
-
|
242
|
-
|
236
|
+
let closest: MediaFragment | undefined;
|
237
|
+
BinarySearch.search(fragments, (candidate) => {
|
238
|
+
if (candidate.cc < cc) {
|
239
|
+
return 1;
|
240
|
+
}
|
241
|
+
if (candidate.cc > cc) {
|
242
|
+
return -1;
|
243
|
+
}
|
244
|
+
closest = candidate;
|
245
|
+
if (candidate.end <= pos) {
|
243
246
|
return 1;
|
244
|
-
}
|
247
|
+
}
|
248
|
+
if (candidate.start > pos) {
|
245
249
|
return -1;
|
246
|
-
} else {
|
247
|
-
return 0;
|
248
250
|
}
|
251
|
+
return 0;
|
249
252
|
});
|
253
|
+
return closest || null;
|
250
254
|
}
|
251
255
|
}
|
252
256
|
return null;
|
@@ -2437,7 +2437,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
2437
2437
|
}
|
2438
2438
|
|
2439
2439
|
private bufferAssetPlayer(player: HlsAssetPlayer, media: HTMLMediaElement) {
|
2440
|
-
const { interstitial, assetItem
|
2440
|
+
const { interstitial, assetItem } = player;
|
2441
2441
|
const scheduleIndex = this.schedule.findEventIndex(interstitial.identifier);
|
2442
2442
|
const item = this.schedule.items?.[scheduleIndex];
|
2443
2443
|
if (!item) {
|