hls.js 1.5.10-0.canary.10321 → 1.5.10-0.canary.10326

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.
@@ -501,7 +501,7 @@ function enableLogs(debugConfig, context, id) {
501
501
  // Some browsers don't allow to use bind on console object anyway
502
502
  // fallback to default if needed
503
503
  try {
504
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.10-0.canary.10321"}`);
504
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.10-0.canary.10326"}`);
505
505
  } catch (e) {
506
506
  /* log fn threw an exception. All logger methods are no-ops. */
507
507
  return createLogger();
@@ -5262,7 +5262,7 @@ function findFragmentByPDT(fragments, PDTValue, maxFragLookUpTolerance) {
5262
5262
  * @param maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous
5263
5263
  * @returns a matching fragment or null
5264
5264
  */
5265
- function findFragmentByPTS(fragPrevious, fragments, bufferEnd = 0, maxFragLookUpTolerance = 0) {
5265
+ function findFragmentByPTS(fragPrevious, fragments, bufferEnd = 0, maxFragLookUpTolerance = 0, nextFragLookupTolerance = 0.005) {
5266
5266
  let fragNext = null;
5267
5267
  if (fragPrevious) {
5268
5268
  fragNext = fragments[fragPrevious.sn - fragments[0].sn + 1] || null;
@@ -5275,7 +5275,7 @@ function findFragmentByPTS(fragPrevious, fragments, bufferEnd = 0, maxFragLookUp
5275
5275
  fragNext = fragments[0];
5276
5276
  }
5277
5277
  // Prefer the next fragment if it's within tolerance
5278
- if (fragNext && (!fragPrevious || fragPrevious.level === fragNext.level) && fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext) === 0) {
5278
+ if (fragNext && ((!fragPrevious || fragPrevious.level === fragNext.level) && fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext) === 0 || fragmentWithinFastStartSwitch(fragNext, fragPrevious, Math.min(nextFragLookupTolerance, maxFragLookUpTolerance)))) {
5279
5279
  return fragNext;
5280
5280
  }
5281
5281
  // We might be seeking past the tolerance so find the best match
@@ -5286,6 +5286,18 @@ function findFragmentByPTS(fragPrevious, fragments, bufferEnd = 0, maxFragLookUp
5286
5286
  // If no match was found return the next fragment after fragPrevious, or null
5287
5287
  return fragNext;
5288
5288
  }
5289
+ function fragmentWithinFastStartSwitch(fragNext, fragPrevious, nextFragLookupTolerance) {
5290
+ if (fragPrevious && fragPrevious.start === 0 && fragPrevious.level < fragNext.level && (fragPrevious.endPTS || 0) > 0) {
5291
+ const firstDuration = fragPrevious.tagList.reduce((duration, tag) => {
5292
+ if (tag[0] === 'INF') {
5293
+ duration += parseFloat(tag[1]);
5294
+ }
5295
+ return duration;
5296
+ }, nextFragLookupTolerance);
5297
+ return fragNext.start <= firstDuration;
5298
+ }
5299
+ return false;
5300
+ }
5289
5301
 
5290
5302
  /**
5291
5303
  * The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.
@@ -12473,7 +12485,7 @@ class BaseStreamController extends TaskLoop {
12473
12485
  if (this.state === State.STOPPED || this.state === State.ERROR) {
12474
12486
  return;
12475
12487
  }
12476
- this.warn(reason);
12488
+ this.warn(`Frag error: ${(reason == null ? void 0 : reason.message) || reason}`);
12477
12489
  this.resetFragmentLoading(frag);
12478
12490
  });
12479
12491
  }
@@ -13170,7 +13182,9 @@ class BaseStreamController extends TaskLoop {
13170
13182
  const {
13171
13183
  fragmentHint
13172
13184
  } = levelDetails;
13173
- const tolerance = config.maxFragLookUpTolerance;
13185
+ const {
13186
+ maxFragLookUpTolerance
13187
+ } = config;
13174
13188
  const partList = levelDetails.partList;
13175
13189
  const loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
13176
13190
  if (loadingParts && fragmentHint && !this.bitrateTest) {
@@ -13180,7 +13194,7 @@ class BaseStreamController extends TaskLoop {
13180
13194
  }
13181
13195
  let frag;
13182
13196
  if (bufferEnd < end) {
13183
- const lookupTolerance = bufferEnd > end - tolerance ? 0 : tolerance;
13197
+ const lookupTolerance = bufferEnd > end - maxFragLookUpTolerance ? 0 : maxFragLookUpTolerance;
13184
13198
  // Remove the tolerance if it would put the bufferEnd past the actual end of stream
13185
13199
  // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)
13186
13200
  frag = findFragmentByPTS(fragPrevious, fragments, bufferEnd, lookupTolerance);
@@ -15449,7 +15463,7 @@ class TSDemuxer {
15449
15463
  if (stt) {
15450
15464
  offset += data[offset] + 1;
15451
15465
  }
15452
- const parsedPIDs = parsePMT(data, offset, this.typeSupported, isSampleAes);
15466
+ const parsedPIDs = parsePMT(data, offset, this.typeSupported, isSampleAes, this.observer);
15453
15467
 
15454
15468
  // only update track id if track PID found while parsing PMT
15455
15469
  // this is to avoid resetting the PID to -1 in case
@@ -15492,14 +15506,7 @@ class TSDemuxer {
15492
15506
  }
15493
15507
  }
15494
15508
  if (tsPacketErrors > 0) {
15495
- const error = new Error(`Found ${tsPacketErrors} TS packet/s that do not start with 0x47`);
15496
- this.observer.emit(Events.ERROR, Events.ERROR, {
15497
- type: ErrorTypes.MEDIA_ERROR,
15498
- details: ErrorDetails.FRAG_PARSING_ERROR,
15499
- fatal: false,
15500
- error,
15501
- reason: error.message
15502
- });
15509
+ emitParsingError(this.observer, new Error(`Found ${tsPacketErrors} TS packet/s that do not start with 0x47`));
15503
15510
  }
15504
15511
  videoTrack.pesData = videoData;
15505
15512
  audioTrack.pesData = audioData;
@@ -15657,16 +15664,7 @@ class TSDemuxer {
15657
15664
  } else {
15658
15665
  reason = 'No ADTS header found in AAC PES';
15659
15666
  }
15660
- const error = new Error(reason);
15661
- logger.warn(`parsing error: ${reason}`);
15662
- this.observer.emit(Events.ERROR, Events.ERROR, {
15663
- type: ErrorTypes.MEDIA_ERROR,
15664
- details: ErrorDetails.FRAG_PARSING_ERROR,
15665
- fatal: false,
15666
- levelRetry: recoverable,
15667
- error,
15668
- reason
15669
- });
15667
+ emitParsingError(this.observer, new Error(reason), recoverable);
15670
15668
  if (!recoverable) {
15671
15669
  return;
15672
15670
  }
@@ -15752,7 +15750,7 @@ function parsePAT(data, offset) {
15752
15750
  // skip the PSI header and parse the first PMT entry
15753
15751
  return (data[offset + 10] & 0x1f) << 8 | data[offset + 11];
15754
15752
  }
15755
- function parsePMT(data, offset, typeSupported, isSampleAes) {
15753
+ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
15756
15754
  const result = {
15757
15755
  audioPid: -1,
15758
15756
  videoPid: -1,
@@ -15860,11 +15858,13 @@ function parsePMT(data, offset, typeSupported, isSampleAes) {
15860
15858
  case 0xc2: // SAMPLE-AES EC3
15861
15859
  /* falls through */
15862
15860
  case 0x87:
15863
- throw new Error('Unsupported EC-3 in M2TS found');
15861
+ emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'));
15862
+ return result;
15864
15863
  case 0x24:
15865
15864
  // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
15866
15865
  {
15867
- throw new Error('Unsupported HEVC in M2TS found');
15866
+ emitParsingError(observer, new Error('Unsupported HEVC in M2TS found'));
15867
+ return result;
15868
15868
  }
15869
15869
  }
15870
15870
  // move to the next table entry
@@ -15873,6 +15873,17 @@ function parsePMT(data, offset, typeSupported, isSampleAes) {
15873
15873
  }
15874
15874
  return result;
15875
15875
  }
15876
+ function emitParsingError(observer, error, levelRetry) {
15877
+ logger.warn(`parsing error: ${error.message}`);
15878
+ observer.emit(Events.ERROR, Events.ERROR, {
15879
+ type: ErrorTypes.MEDIA_ERROR,
15880
+ details: ErrorDetails.FRAG_PARSING_ERROR,
15881
+ fatal: false,
15882
+ levelRetry,
15883
+ error,
15884
+ reason: error.message
15885
+ });
15886
+ }
15876
15887
  function logEncryptedSamplesFoundInUnencryptedStream(type) {
15877
15888
  logger.log(`${type} with AES-128-CBC encryption found in unencrypted stream`);
15878
15889
  }
@@ -18610,10 +18621,6 @@ class TransmuxerInterface {
18610
18621
  this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
18611
18622
  this.observer.on(Events.ERROR, forwardMessage);
18612
18623
  const m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
18613
-
18614
- // navigator.vendor is not always available in Web Worker
18615
- // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
18616
- const vendor = navigator.vendor;
18617
18624
  if (this.useWorker && typeof Worker !== 'undefined') {
18618
18625
  const canCreateWorker = config.workerPath || hasUMDWorker();
18619
18626
  if (canCreateWorker) {
@@ -18625,7 +18632,7 @@ class TransmuxerInterface {
18625
18632
  logger.log(`injecting Web Worker for "${id}"`);
18626
18633
  this.workerContext = injectWorker();
18627
18634
  }
18628
- this.onwmsg = ev => this.onWorkerMessage(ev);
18635
+ this.onwmsg = event => this.onWorkerMessage(event);
18629
18636
  const {
18630
18637
  worker
18631
18638
  } = this.workerContext;
@@ -18645,7 +18652,7 @@ class TransmuxerInterface {
18645
18652
  worker.postMessage({
18646
18653
  cmd: 'init',
18647
18654
  typeSupported: m2tsTypeSupported,
18648
- vendor: vendor,
18655
+ vendor: '',
18649
18656
  id: id,
18650
18657
  config: JSON.stringify(config)
18651
18658
  });
@@ -18653,12 +18660,12 @@ class TransmuxerInterface {
18653
18660
  logger.warn(`Error setting up "${id}" Web Worker, fallback to inline`, err);
18654
18661
  this.resetWorker();
18655
18662
  this.error = null;
18656
- this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, vendor, id);
18663
+ this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id);
18657
18664
  }
18658
18665
  return;
18659
18666
  }
18660
18667
  }
18661
- this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, vendor, id);
18668
+ this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id);
18662
18669
  }
18663
18670
  resetWorker() {
18664
18671
  if (this.workerContext) {
@@ -18810,9 +18817,16 @@ class TransmuxerInterface {
18810
18817
  });
18811
18818
  this.onFlush(chunkMeta);
18812
18819
  }
18813
- onWorkerMessage(ev) {
18814
- const data = ev.data;
18820
+ onWorkerMessage(event) {
18821
+ const data = event.data;
18822
+ if (!(data != null && data.event)) {
18823
+ logger.warn(`worker message received with no ${data ? 'event name' : 'data'}`);
18824
+ return;
18825
+ }
18815
18826
  const hls = this.hls;
18827
+ if (!this.hls) {
18828
+ return;
18829
+ }
18816
18830
  switch (data.event) {
18817
18831
  case 'init':
18818
18832
  {
@@ -20208,7 +20222,8 @@ class StreamController extends BaseStreamController {
20208
20222
  // In the case that AAC and HE-AAC audio codecs are signalled in manifest,
20209
20223
  // force HE-AAC, as it seems that most browsers prefers it.
20210
20224
  // don't force HE-AAC if mono stream, or in Firefox
20211
- if (audio.metadata.channelCount !== 1 && ua.indexOf('firefox') === -1) {
20225
+ const audioMetadata = audio.metadata;
20226
+ if (audioMetadata && 'channelCount' in audioMetadata && (audioMetadata.channelCount || 1) !== 1 && ua.indexOf('firefox') === -1) {
20212
20227
  audioCodec = 'mp4a.40.5';
20213
20228
  }
20214
20229
  }
@@ -20371,7 +20386,7 @@ class Hls {
20371
20386
  * Get the video-dev/hls.js package version.
20372
20387
  */
20373
20388
  static get version() {
20374
- return "1.5.10-0.canary.10321";
20389
+ return "1.5.10-0.canary.10326";
20375
20390
  }
20376
20391
 
20377
20392
  /**