hls.js 1.5.14-0.canary.10559 → 1.5.15

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.
Files changed (109) hide show
  1. package/README.md +3 -4
  2. package/dist/hls-demo.js +38 -41
  3. package/dist/hls-demo.js.map +1 -1
  4. package/dist/hls.js +2911 -4558
  5. package/dist/hls.js.d.ts +112 -186
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +2291 -3311
  8. package/dist/hls.light.js.map +1 -1
  9. package/dist/hls.light.min.js +1 -1
  10. package/dist/hls.light.min.js.map +1 -1
  11. package/dist/hls.light.mjs +1813 -2835
  12. package/dist/hls.light.mjs.map +1 -1
  13. package/dist/hls.min.js +1 -1
  14. package/dist/hls.min.js.map +1 -1
  15. package/dist/hls.mjs +4707 -6356
  16. package/dist/hls.mjs.map +1 -1
  17. package/dist/hls.worker.js +1 -1
  18. package/dist/hls.worker.js.map +1 -1
  19. package/package.json +42 -42
  20. package/src/config.ts +2 -5
  21. package/src/controller/abr-controller.ts +25 -39
  22. package/src/controller/audio-stream-controller.ts +136 -156
  23. package/src/controller/audio-track-controller.ts +1 -1
  24. package/src/controller/base-playlist-controller.ts +10 -27
  25. package/src/controller/base-stream-controller.ts +107 -263
  26. package/src/controller/buffer-controller.ts +97 -250
  27. package/src/controller/buffer-operation-queue.ts +19 -16
  28. package/src/controller/cap-level-controller.ts +2 -3
  29. package/src/controller/cmcd-controller.ts +14 -51
  30. package/src/controller/content-steering-controller.ts +15 -29
  31. package/src/controller/eme-controller.ts +23 -10
  32. package/src/controller/error-controller.ts +22 -28
  33. package/src/controller/fps-controller.ts +3 -8
  34. package/src/controller/fragment-finders.ts +16 -44
  35. package/src/controller/fragment-tracker.ts +25 -58
  36. package/src/controller/gap-controller.ts +16 -43
  37. package/src/controller/id3-track-controller.ts +35 -45
  38. package/src/controller/latency-controller.ts +13 -18
  39. package/src/controller/level-controller.ts +19 -37
  40. package/src/controller/stream-controller.ts +83 -100
  41. package/src/controller/subtitle-stream-controller.ts +47 -35
  42. package/src/controller/subtitle-track-controller.ts +3 -5
  43. package/src/controller/timeline-controller.ts +22 -20
  44. package/src/crypt/aes-crypto.ts +2 -21
  45. package/src/crypt/decrypter.ts +16 -32
  46. package/src/crypt/fast-aes-key.ts +5 -28
  47. package/src/demux/audio/aacdemuxer.ts +5 -5
  48. package/src/demux/audio/ac3-demuxer.ts +4 -5
  49. package/src/demux/audio/adts.ts +4 -9
  50. package/src/demux/audio/base-audio-demuxer.ts +15 -21
  51. package/src/demux/audio/mp3demuxer.ts +3 -4
  52. package/src/demux/audio/mpegaudio.ts +1 -1
  53. package/src/demux/id3.ts +411 -0
  54. package/src/demux/inject-worker.ts +4 -38
  55. package/src/demux/mp4demuxer.ts +8 -17
  56. package/src/demux/sample-aes.ts +0 -2
  57. package/src/demux/transmuxer-interface.ts +83 -106
  58. package/src/demux/transmuxer-worker.ts +77 -111
  59. package/src/demux/transmuxer.ts +22 -46
  60. package/src/demux/tsdemuxer.ts +65 -131
  61. package/src/demux/video/avc-video-parser.ts +156 -219
  62. package/src/demux/video/base-video-parser.ts +9 -133
  63. package/src/demux/video/exp-golomb.ts +208 -0
  64. package/src/errors.ts +0 -2
  65. package/src/events.ts +1 -8
  66. package/src/exports-named.ts +1 -1
  67. package/src/hls.ts +48 -97
  68. package/src/loader/date-range.ts +5 -71
  69. package/src/loader/fragment-loader.ts +21 -23
  70. package/src/loader/fragment.ts +4 -8
  71. package/src/loader/key-loader.ts +1 -3
  72. package/src/loader/level-details.ts +6 -6
  73. package/src/loader/level-key.ts +9 -10
  74. package/src/loader/m3u8-parser.ts +144 -138
  75. package/src/loader/playlist-loader.ts +7 -5
  76. package/src/remux/mp4-generator.ts +1 -196
  77. package/src/remux/mp4-remuxer.ts +84 -55
  78. package/src/remux/passthrough-remuxer.ts +8 -23
  79. package/src/task-loop.ts +2 -5
  80. package/src/types/component-api.ts +1 -3
  81. package/src/types/demuxer.ts +1 -3
  82. package/src/types/events.ts +6 -19
  83. package/src/types/fragment-tracker.ts +2 -2
  84. package/src/types/general.ts +6 -0
  85. package/src/types/media-playlist.ts +1 -9
  86. package/src/types/remuxer.ts +1 -1
  87. package/src/utils/attr-list.ts +9 -96
  88. package/src/utils/buffer-helper.ts +31 -12
  89. package/src/utils/cea-608-parser.ts +3 -1
  90. package/src/utils/codecs.ts +5 -34
  91. package/src/utils/discontinuities.ts +47 -21
  92. package/src/utils/fetch-loader.ts +1 -1
  93. package/src/utils/hdr.ts +7 -4
  94. package/src/utils/imsc1-ttml-parser.ts +1 -1
  95. package/src/utils/keysystem-util.ts +6 -1
  96. package/src/utils/level-helper.ts +44 -71
  97. package/src/utils/logger.ts +23 -58
  98. package/src/utils/mp4-tools.ts +3 -5
  99. package/src/utils/rendition-helper.ts +74 -100
  100. package/src/utils/variable-substitution.ts +19 -0
  101. package/src/utils/webvtt-parser.ts +12 -2
  102. package/dist/hls.d.mts +0 -3179
  103. package/dist/hls.d.ts +0 -3179
  104. package/src/crypt/decrypter-aes-mode.ts +0 -4
  105. package/src/demux/video/hevc-video-parser.ts +0 -718
  106. package/src/utils/encryption-methods-util.ts +0 -21
  107. package/src/utils/hash.ts +0 -10
  108. package/src/utils/utf8-utils.ts +0 -18
  109. package/src/version.ts +0 -1
@@ -4,31 +4,28 @@ import { ErrorTypes, ErrorDetails } from '../errors';
4
4
  import Decrypter from '../crypt/decrypter';
5
5
  import AACDemuxer from './audio/aacdemuxer';
6
6
  import MP4Demuxer from '../demux/mp4demuxer';
7
- import TSDemuxer from '../demux/tsdemuxer';
7
+ import TSDemuxer, { TypeSupported } from '../demux/tsdemuxer';
8
8
  import MP3Demuxer from './audio/mp3demuxer';
9
9
  import { AC3Demuxer } from './audio/ac3-demuxer';
10
10
  import MP4Remuxer from '../remux/mp4-remuxer';
11
11
  import PassThroughRemuxer from '../remux/passthrough-remuxer';
12
- import { PlaylistLevelType } from '../types/loader';
13
- import {
14
- isFullSegmentEncryption,
15
- getAesModeFromFullSegmentMethod,
16
- } from '../utils/encryption-methods-util';
12
+ import { logger } from '../utils/logger';
17
13
  import type { Demuxer, DemuxerResult, KeyData } from '../types/demuxer';
18
14
  import type { Remuxer } from '../types/remuxer';
19
15
  import type { TransmuxerResult, ChunkMetadata } from '../types/transmuxer';
20
16
  import type { HlsConfig } from '../config';
21
17
  import type { DecryptData } from '../loader/level-key';
22
- import type { TypeSupported } from '../utils/codecs';
23
- import type { ILogger } from '../utils/logger';
18
+ import type { PlaylistLevelType } from '../types/loader';
24
19
  import type { RationalTimestamp } from '../utils/timescale-conversion';
20
+ import { optionalSelf } from '../utils/global';
25
21
 
26
- let now: () => number;
22
+ let now;
27
23
  // performance.now() not available on WebWorker, at least on Safari Desktop
28
24
  try {
29
25
  now = self.performance.now.bind(self.performance);
30
26
  } catch (err) {
31
- now = Date.now;
27
+ logger.debug('Unable to use Performance API on this environment');
28
+ now = optionalSelf?.Date.now;
32
29
  }
33
30
 
34
31
  type MuxConfig =
@@ -50,11 +47,11 @@ if (__USE_M2TS_ADVANCED_CODECS__) {
50
47
  }
51
48
 
52
49
  export default class Transmuxer {
53
- private asyncResult: boolean = false;
54
- private logger: ILogger;
50
+ public async: boolean = false;
55
51
  private observer: HlsEventEmitter;
56
52
  private typeSupported: TypeSupported;
57
53
  private config: HlsConfig;
54
+ private vendor: string;
58
55
  private id: PlaylistLevelType;
59
56
  private demuxer?: Demuxer;
60
57
  private remuxer?: Remuxer;
@@ -70,13 +67,12 @@ export default class Transmuxer {
70
67
  config: HlsConfig,
71
68
  vendor: string,
72
69
  id: PlaylistLevelType,
73
- logger: ILogger,
74
70
  ) {
75
71
  this.observer = observer;
76
72
  this.typeSupported = typeSupported;
77
73
  this.config = config;
74
+ this.vendor = vendor;
78
75
  this.id = id;
79
- this.logger = logger;
80
76
  }
81
77
 
82
78
  configure(transmuxConfig: TransmuxConfig) {
@@ -118,10 +114,8 @@ export default class Transmuxer {
118
114
  } = transmuxConfig;
119
115
 
120
116
  const keyData = getEncryptionType(uintData, decryptdata);
121
- if (keyData && isFullSegmentEncryption(keyData.method)) {
117
+ if (keyData && keyData.method === 'AES-128') {
122
118
  const decrypter = this.getDecrypter();
123
- const aesMode = getAesModeFromFullSegmentMethod(keyData.method);
124
-
125
119
  // Software decryption is synchronous; webCrypto is not
126
120
  if (decrypter.isSync()) {
127
121
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
@@ -130,7 +124,6 @@ export default class Transmuxer {
130
124
  uintData,
131
125
  keyData.key.buffer,
132
126
  keyData.iv.buffer,
133
- aesMode,
134
127
  );
135
128
  // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
136
129
  const loadingParts = chunkMeta.part > -1;
@@ -143,14 +136,8 @@ export default class Transmuxer {
143
136
  }
144
137
  uintData = new Uint8Array(decryptedData);
145
138
  } else {
146
- this.asyncResult = true;
147
139
  this.decryptionPromise = decrypter
148
- .webCryptoDecrypt(
149
- uintData,
150
- keyData.key.buffer,
151
- keyData.iv.buffer,
152
- aesMode,
153
- )
140
+ .webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer)
154
141
  .then((decryptedData): TransmuxerResult => {
155
142
  // Calling push here is important; if flush() is called while this is still resolving, this ensures that
156
143
  // the decrypted data has been transmuxed
@@ -162,7 +149,7 @@ export default class Transmuxer {
162
149
  this.decryptionPromise = null;
163
150
  return result;
164
151
  });
165
- return this.decryptionPromise;
152
+ return this.decryptionPromise!;
166
153
  }
167
154
  }
168
155
 
@@ -170,7 +157,7 @@ export default class Transmuxer {
170
157
  if (resetMuxers) {
171
158
  const error = this.configureTransmuxer(uintData);
172
159
  if (error) {
173
- this.logger.warn(`[transmuxer] ${error.message}`);
160
+ logger.warn(`[transmuxer] ${error.message}`);
174
161
  this.observer.emit(Events.ERROR, Events.ERROR, {
175
162
  type: ErrorTypes.MEDIA_ERROR,
176
163
  details: ErrorDetails.FRAG_PARSING_ERROR,
@@ -208,8 +195,6 @@ export default class Transmuxer {
208
195
  accurateTimeOffset,
209
196
  chunkMeta,
210
197
  );
211
- this.asyncResult = isPromise(result);
212
-
213
198
  const currentState = this.currentTransmuxState;
214
199
 
215
200
  currentState.contiguous = true;
@@ -230,7 +215,6 @@ export default class Transmuxer {
230
215
  const { decrypter, currentTransmuxState, decryptionPromise } = this;
231
216
 
232
217
  if (decryptionPromise) {
233
- this.asyncResult = true;
234
218
  // Upon resolution, the decryption promise calls push() and returns its TransmuxerResult up the stack. Therefore
235
219
  // only flushing is required for async decryption
236
220
  return decryptionPromise.then(() => {
@@ -257,16 +241,11 @@ export default class Transmuxer {
257
241
  if (!demuxer || !remuxer) {
258
242
  // If probing failed, then Hls.js has been given content its not able to handle
259
243
  stats.executeEnd = now();
260
- const emptyResults = [emptyResult(chunkMeta)];
261
- if (this.asyncResult) {
262
- return Promise.resolve(emptyResults);
263
- }
264
- return emptyResults;
244
+ return [emptyResult(chunkMeta)];
265
245
  }
266
246
 
267
247
  const demuxResultOrPromise = demuxer.flush(timeOffset);
268
248
  if (isPromise(demuxResultOrPromise)) {
269
- this.asyncResult = true;
270
249
  // Decrypt final SAMPLE-AES samples
271
250
  return demuxResultOrPromise.then((demuxResult) => {
272
251
  this.flushRemux(transmuxResults, demuxResult, chunkMeta);
@@ -275,9 +254,6 @@ export default class Transmuxer {
275
254
  }
276
255
 
277
256
  this.flushRemux(transmuxResults, demuxResultOrPromise, chunkMeta);
278
- if (this.asyncResult) {
279
- return Promise.resolve(transmuxResults);
280
- }
281
257
  return transmuxResults;
282
258
  }
283
259
 
@@ -288,10 +264,10 @@ export default class Transmuxer {
288
264
  ) {
289
265
  const { audioTrack, videoTrack, id3Track, textTrack } = demuxResult;
290
266
  const { accurateTimeOffset, timeOffset } = this.currentTransmuxState;
291
- this.logger.log(
292
- `[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${
267
+ logger.log(
268
+ `[transmuxer.ts]: Flushed fragment ${chunkMeta.sn}${
293
269
  chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : ''
294
- } of ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'} ${chunkMeta.level}`,
270
+ } of level ${chunkMeta.level}`,
295
271
  );
296
272
  const remuxResult = this.remuxer!.remux(
297
273
  audioTrack,
@@ -445,11 +421,11 @@ export default class Transmuxer {
445
421
  }
446
422
 
447
423
  private configureTransmuxer(data: Uint8Array): void | Error {
448
- const { config, observer, typeSupported } = this;
424
+ const { config, observer, typeSupported, vendor } = this;
449
425
  // probe for content type
450
426
  let mux;
451
427
  for (let i = 0, len = muxConfig.length; i < len; i++) {
452
- if (muxConfig[i].demux?.probe(data, this.logger)) {
428
+ if (muxConfig[i].demux?.probe(data)) {
453
429
  mux = muxConfig[i];
454
430
  break;
455
431
  }
@@ -463,10 +439,10 @@ export default class Transmuxer {
463
439
  const Remuxer: MuxConfig['remux'] = mux.remux;
464
440
  const Demuxer: MuxConfig['demux'] = mux.demux;
465
441
  if (!remuxer || !(remuxer instanceof Remuxer)) {
466
- this.remuxer = new Remuxer(observer, config, typeSupported, this.logger);
442
+ this.remuxer = new Remuxer(observer, config, typeSupported, vendor);
467
443
  }
468
444
  if (!demuxer || !(demuxer instanceof Demuxer)) {
469
- this.demuxer = new Demuxer(observer, config, typeSupported, this.logger);
445
+ this.demuxer = new Demuxer(observer, config, typeSupported);
470
446
  this.probe = Demuxer.probe;
471
447
  }
472
448
  }
@@ -2,7 +2,7 @@
2
2
  * highly optimized TS demuxer:
3
3
  * parse PAT, PMT
4
4
  * extract PES packet from audio and video PIDs
5
- * extract AVC/H264 (or HEVC/H265) NAL units and AAC/ADTS samples from PES packet
5
+ * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
6
6
  * trigger the remuxer upon parsing completion
7
7
  * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.
8
8
  * it also controls the remuxing process :
@@ -12,31 +12,28 @@
12
12
  import * as ADTS from './audio/adts';
13
13
  import * as MpegAudio from './audio/mpegaudio';
14
14
  import * as AC3 from './audio/ac3-demuxer';
15
- import BaseVideoParser from './video/base-video-parser';
16
15
  import AvcVideoParser from './video/avc-video-parser';
17
- import HevcVideoParser from './video/hevc-video-parser';
18
16
  import SampleAesDecrypter from './sample-aes';
19
17
  import { Events } from '../events';
20
18
  import { appendUint8Array, RemuxerTrackIdConfig } from '../utils/mp4-tools';
19
+ import { logger } from '../utils/logger';
21
20
  import { ErrorTypes, ErrorDetails } from '../errors';
22
21
  import type { HlsConfig } from '../config';
23
22
  import type { HlsEventEmitter } from '../events';
24
- import type { TypeSupported } from '../utils/codecs';
25
- import type { ILogger } from '../utils/logger';
26
23
  import {
24
+ DemuxedVideoTrack,
25
+ DemuxedAudioTrack,
26
+ DemuxedTrack,
27
+ Demuxer,
28
+ DemuxerResult,
29
+ VideoSample,
30
+ DemuxedMetadataTrack,
31
+ DemuxedUserdataTrack,
32
+ ElementaryStreamData,
33
+ KeyData,
27
34
  MetadataSchema,
28
- type DemuxedVideoTrack,
29
- type DemuxedAudioTrack,
30
- type DemuxedTrack,
31
- type Demuxer,
32
- type DemuxerResult,
33
- type VideoSample,
34
- type DemuxedMetadataTrack,
35
- type DemuxedUserdataTrack,
36
- type ElementaryStreamData,
37
- type KeyData,
38
35
  } from '../types/demuxer';
39
- import type { AudioFrame } from '../types/demuxer';
36
+ import { AudioFrame } from '../types/demuxer';
40
37
 
41
38
  export type ParsedTimestamp = {
42
39
  pts?: number;
@@ -51,18 +48,24 @@ export type PES = ParsedTimestamp & {
51
48
  export type ParsedVideoSample = ParsedTimestamp &
52
49
  Omit<VideoSample, 'pts' | 'dts'>;
53
50
 
51
+ export interface TypeSupported {
52
+ mpeg: boolean;
53
+ mp3: boolean;
54
+ ac3: boolean;
55
+ }
56
+
54
57
  const PACKET_LENGTH = 188;
55
58
 
56
59
  class TSDemuxer implements Demuxer {
57
- private readonly logger: ILogger;
58
60
  private readonly observer: HlsEventEmitter;
59
61
  private readonly config: HlsConfig;
60
- private readonly typeSupported: TypeSupported;
62
+ private typeSupported: TypeSupported;
61
63
 
62
64
  private sampleAes: SampleAesDecrypter | null = null;
63
65
  private pmtParsed: boolean = false;
64
66
  private audioCodec?: string;
65
67
  private videoCodec?: string;
68
+ private _duration: number = 0;
66
69
  private _pmtId: number = -1;
67
70
 
68
71
  private _videoTrack?: DemuxedVideoTrack;
@@ -71,22 +74,20 @@ class TSDemuxer implements Demuxer {
71
74
  private _txtTrack?: DemuxedUserdataTrack;
72
75
  private aacOverFlow: AudioFrame | null = null;
73
76
  private remainderData: Uint8Array | null = null;
74
- private videoParser: BaseVideoParser | null;
77
+ private videoParser: AvcVideoParser;
75
78
 
76
79
  constructor(
77
80
  observer: HlsEventEmitter,
78
81
  config: HlsConfig,
79
82
  typeSupported: TypeSupported,
80
- logger: ILogger,
81
83
  ) {
82
84
  this.observer = observer;
83
85
  this.config = config;
84
86
  this.typeSupported = typeSupported;
85
- this.logger = logger;
86
- this.videoParser = null;
87
+ this.videoParser = new AvcVideoParser();
87
88
  }
88
89
 
89
- static probe(data: Uint8Array, logger: ILogger) {
90
+ static probe(data: Uint8Array) {
90
91
  const syncOffset = TSDemuxer.syncOffset(data);
91
92
  if (syncOffset > 0) {
92
93
  logger.warn(
@@ -181,7 +182,6 @@ class TSDemuxer implements Demuxer {
181
182
  this._pmtId = -1;
182
183
 
183
184
  this._videoTrack = TSDemuxer.createTrack('video') as DemuxedVideoTrack;
184
- this._videoTrack.duration = trackDuration;
185
185
  this._audioTrack = TSDemuxer.createTrack(
186
186
  'audio',
187
187
  trackDuration,
@@ -195,6 +195,7 @@ class TSDemuxer implements Demuxer {
195
195
  this.remainderData = null;
196
196
  this.audioCodec = audioCodec;
197
197
  this.videoCodec = videoCodec;
198
+ this._duration = trackDuration;
198
199
  }
199
200
 
200
201
  public resetTimeStamp() {}
@@ -290,22 +291,14 @@ class TSDemuxer implements Demuxer {
290
291
  switch (pid) {
291
292
  case videoPid:
292
293
  if (stt) {
293
- if (videoData && (pes = parsePES(videoData, this.logger))) {
294
- if (this.videoParser === null) {
295
- switch (videoTrack.segmentCodec) {
296
- case 'avc':
297
- this.videoParser = new AvcVideoParser();
298
- break;
299
- case 'hevc':
300
- if (__USE_M2TS_ADVANCED_CODECS__) {
301
- this.videoParser = new HevcVideoParser();
302
- }
303
- break;
304
- }
305
- }
306
- if (this.videoParser !== null) {
307
- this.videoParser.parsePES(videoTrack, textTrack, pes, false);
308
- }
294
+ if (videoData && (pes = parsePES(videoData))) {
295
+ this.videoParser.parseAVCPES(
296
+ videoTrack,
297
+ textTrack,
298
+ pes,
299
+ false,
300
+ this._duration,
301
+ );
309
302
  }
310
303
 
311
304
  videoData = { data: [], size: 0 };
@@ -317,7 +310,7 @@ class TSDemuxer implements Demuxer {
317
310
  break;
318
311
  case audioPid:
319
312
  if (stt) {
320
- if (audioData && (pes = parsePES(audioData, this.logger))) {
313
+ if (audioData && (pes = parsePES(audioData))) {
321
314
  switch (audioTrack.segmentCodec) {
322
315
  case 'aac':
323
316
  this.parseAACPES(audioTrack, pes);
@@ -341,7 +334,7 @@ class TSDemuxer implements Demuxer {
341
334
  break;
342
335
  case id3Pid:
343
336
  if (stt) {
344
- if (id3Data && (pes = parsePES(id3Data, this.logger))) {
337
+ if (id3Data && (pes = parsePES(id3Data))) {
345
338
  this.parseID3PES(id3Track, pes);
346
339
  }
347
340
 
@@ -358,7 +351,7 @@ class TSDemuxer implements Demuxer {
358
351
  }
359
352
 
360
353
  pmtId = this._pmtId = parsePAT(data, offset);
361
- // this.logger.log('PMT PID:' + this._pmtId);
354
+ // logger.log('PMT PID:' + this._pmtId);
362
355
  break;
363
356
  case pmtId: {
364
357
  if (stt) {
@@ -371,7 +364,6 @@ class TSDemuxer implements Demuxer {
371
364
  this.typeSupported,
372
365
  isSampleAes,
373
366
  this.observer,
374
- this.logger,
375
367
  );
376
368
 
377
369
  // only update track id if track PID found while parsing PMT
@@ -397,7 +389,7 @@ class TSDemuxer implements Demuxer {
397
389
  }
398
390
 
399
391
  if (unknownPID !== null && !pmtParsed) {
400
- this.logger.warn(
392
+ logger.warn(
401
393
  `MPEG-TS PMT found at ${start} after unknown PID '${unknownPID}'. Backtracking to sync byte @${syncOffset} to parse all TS packets.`,
402
394
  );
403
395
  unknownPID = null;
@@ -425,8 +417,6 @@ class TSDemuxer implements Demuxer {
425
417
  new Error(
426
418
  `Found ${tsPacketErrors} TS packet/s that do not start with 0x47`,
427
419
  ),
428
- undefined,
429
- this.logger,
430
420
  );
431
421
  }
432
422
 
@@ -476,34 +466,21 @@ class TSDemuxer implements Demuxer {
476
466
  const id3Data = id3Track.pesData;
477
467
  // try to parse last PES packets
478
468
  let pes: PES | null;
479
- if (videoData && (pes = parsePES(videoData, this.logger))) {
480
- if (this.videoParser === null) {
481
- switch (videoTrack.segmentCodec) {
482
- case 'avc':
483
- this.videoParser = new AvcVideoParser();
484
- break;
485
- case 'hevc':
486
- if (__USE_M2TS_ADVANCED_CODECS__) {
487
- this.videoParser = new HevcVideoParser();
488
- }
489
- break;
490
- }
491
- }
492
- if (this.videoParser !== null) {
493
- this.videoParser.parsePES(
494
- videoTrack as DemuxedVideoTrack,
495
- textTrack as DemuxedUserdataTrack,
496
- pes,
497
- true,
498
- );
499
- videoTrack.pesData = null;
500
- }
469
+ if (videoData && (pes = parsePES(videoData))) {
470
+ this.videoParser.parseAVCPES(
471
+ videoTrack as DemuxedVideoTrack,
472
+ textTrack as DemuxedUserdataTrack,
473
+ pes,
474
+ true,
475
+ this._duration,
476
+ );
477
+ videoTrack.pesData = null;
501
478
  } else {
502
479
  // either avcData null or PES truncated, keep it for next frag parsing
503
480
  videoTrack.pesData = videoData;
504
481
  }
505
482
 
506
- if (audioData && (pes = parsePES(audioData, this.logger))) {
483
+ if (audioData && (pes = parsePES(audioData))) {
507
484
  switch (audioTrack.segmentCodec) {
508
485
  case 'aac':
509
486
  this.parseAACPES(audioTrack, pes);
@@ -520,7 +497,7 @@ class TSDemuxer implements Demuxer {
520
497
  audioTrack.pesData = null;
521
498
  } else {
522
499
  if (audioData?.size) {
523
- this.logger.log(
500
+ logger.log(
524
501
  'last AAC PES packet truncated,might overlap between fragments',
525
502
  );
526
503
  }
@@ -529,7 +506,7 @@ class TSDemuxer implements Demuxer {
529
506
  audioTrack.pesData = audioData;
530
507
  }
531
508
 
532
- if (id3Data && (pes = parsePES(id3Data, this.logger))) {
509
+ if (id3Data && (pes = parsePES(id3Data))) {
533
510
  this.parseID3PES(id3Track, pes);
534
511
  id3Track.pesData = null;
535
512
  } else {
@@ -582,21 +559,7 @@ class TSDemuxer implements Demuxer {
582
559
  }
583
560
 
584
561
  public destroy() {
585
- if (this.observer) {
586
- this.observer.removeAllListeners();
587
- }
588
- // @ts-ignore
589
- this.config = this.logger = this.observer = null;
590
- this.aacOverFlow =
591
- this.videoParser =
592
- this.remainderData =
593
- this.sampleAes =
594
- null;
595
- this._videoTrack =
596
- this._audioTrack =
597
- this._id3Track =
598
- this._txtTrack =
599
- undefined;
562
+ this._duration = 0;
600
563
  }
601
564
 
602
565
  private parseAACPES(track: DemuxedAudioTrack, pes: PES) {
@@ -637,12 +600,7 @@ class TSDemuxer implements Demuxer {
637
600
  } else {
638
601
  reason = 'No ADTS header found in AAC PES';
639
602
  }
640
- emitParsingError(
641
- this.observer,
642
- new Error(reason),
643
- recoverable,
644
- this.logger,
645
- );
603
+ emitParsingError(this.observer, new Error(reason), recoverable);
646
604
  if (!recoverable) {
647
605
  return;
648
606
  }
@@ -665,7 +623,7 @@ class TSDemuxer implements Demuxer {
665
623
  const frameDuration = ADTS.getFrameDuration(track.samplerate as number);
666
624
  pts = aacOverFlow.sample.pts + frameDuration;
667
625
  } else {
668
- this.logger.warn('[tsdemuxer]: AAC PES unknown PTS');
626
+ logger.warn('[tsdemuxer]: AAC PES unknown PTS');
669
627
  return;
670
628
  }
671
629
 
@@ -696,7 +654,7 @@ class TSDemuxer implements Demuxer {
696
654
  let offset = 0;
697
655
  const pts = pes.pts;
698
656
  if (pts === undefined) {
699
- this.logger.warn('[tsdemuxer]: MPEG PES unknown PTS');
657
+ logger.warn('[tsdemuxer]: MPEG PES unknown PTS');
700
658
  return;
701
659
  }
702
660
 
@@ -728,7 +686,7 @@ class TSDemuxer implements Demuxer {
728
686
  const data = pes.data;
729
687
  const pts = pes.pts;
730
688
  if (pts === undefined) {
731
- this.logger.warn('[tsdemuxer]: AC3 PES unknown PTS');
689
+ logger.warn('[tsdemuxer]: AC3 PES unknown PTS');
732
690
  return;
733
691
  }
734
692
  const length = data.length;
@@ -747,7 +705,7 @@ class TSDemuxer implements Demuxer {
747
705
 
748
706
  private parseID3PES(id3Track: DemuxedMetadataTrack, pes: PES) {
749
707
  if (pes.pts === undefined) {
750
- this.logger.warn('[tsdemuxer]: ID3 PES unknown PTS');
708
+ logger.warn('[tsdemuxer]: ID3 PES unknown PTS');
751
709
  return;
752
710
  }
753
711
  const id3Sample = Object.assign({}, pes as Required<PES>, {
@@ -774,7 +732,6 @@ function parsePMT(
774
732
  typeSupported: TypeSupported,
775
733
  isSampleAes: boolean,
776
734
  observer: HlsEventEmitter,
777
- logger: ILogger,
778
735
  ) {
779
736
  const result = {
780
737
  audioPid: -1,
@@ -797,7 +754,7 @@ function parsePMT(
797
754
  switch (data[offset]) {
798
755
  case 0xcf: // SAMPLE-AES AAC
799
756
  if (!isSampleAes) {
800
- logEncryptedSamplesFoundInUnencryptedStream('ADTS AAC', logger);
757
+ logEncryptedSamplesFoundInUnencryptedStream('ADTS AAC');
801
758
  break;
802
759
  }
803
760
  /* falls through */
@@ -820,7 +777,7 @@ function parsePMT(
820
777
 
821
778
  case 0xdb: // SAMPLE-AES AVC
822
779
  if (!isSampleAes) {
823
- logEncryptedSamplesFoundInUnencryptedStream('H.264', logger);
780
+ logEncryptedSamplesFoundInUnencryptedStream('H.264');
824
781
  break;
825
782
  }
826
783
  /* falls through */
@@ -848,7 +805,7 @@ function parsePMT(
848
805
 
849
806
  case 0xc1: // SAMPLE-AES AC3
850
807
  if (!isSampleAes) {
851
- logEncryptedSamplesFoundInUnencryptedStream('AC-3', logger);
808
+ logEncryptedSamplesFoundInUnencryptedStream('AC-3');
852
809
  break;
853
810
  }
854
811
  /* falls through */
@@ -904,31 +861,12 @@ function parsePMT(
904
861
  case 0xc2: // SAMPLE-AES EC3
905
862
  /* falls through */
906
863
  case 0x87:
907
- emitParsingError(
908
- observer,
909
- new Error('Unsupported EC-3 in M2TS found'),
910
- undefined,
911
- logger,
912
- );
864
+ emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'));
913
865
  return result;
914
866
 
915
- case 0x24: // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
916
- if (__USE_M2TS_ADVANCED_CODECS__) {
917
- if (result.videoPid === -1) {
918
- result.videoPid = pid;
919
- result.segmentVideoCodec = 'hevc';
920
- logger.log('HEVC in M2TS found');
921
- }
922
- } else {
923
- emitParsingError(
924
- observer,
925
- new Error('Unsupported HEVC in M2TS found'),
926
- undefined,
927
- logger,
928
- );
929
- return result;
930
- }
931
- break;
867
+ case 0x24:
868
+ emitParsingError(observer, new Error('Unsupported HEVC in M2TS found'));
869
+ return result;
932
870
 
933
871
  default:
934
872
  // logger.log('unknown stream type:' + data[offset]);
@@ -944,8 +882,7 @@ function parsePMT(
944
882
  function emitParsingError(
945
883
  observer: HlsEventEmitter,
946
884
  error: Error,
947
- levelRetry: boolean | undefined,
948
- logger: ILogger,
885
+ levelRetry?: boolean,
949
886
  ) {
950
887
  logger.warn(`parsing error: ${error.message}`);
951
888
  observer.emit(Events.ERROR, Events.ERROR, {
@@ -958,14 +895,11 @@ function emitParsingError(
958
895
  });
959
896
  }
960
897
 
961
- function logEncryptedSamplesFoundInUnencryptedStream(
962
- type: string,
963
- logger: ILogger,
964
- ) {
898
+ function logEncryptedSamplesFoundInUnencryptedStream(type: string) {
965
899
  logger.log(`${type} with AES-128-CBC encryption found in unencrypted stream`);
966
900
  }
967
901
 
968
- function parsePES(stream: ElementaryStreamData, logger: ILogger): PES | null {
902
+ function parsePES(stream: ElementaryStreamData): PES | null {
969
903
  let i = 0;
970
904
  let frag: Uint8Array;
971
905
  let pesLen: number;