hls.js 1.5.9-0.canary.10310 → 1.5.9
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/README.md +3 -4
- package/dist/hls-demo.js +38 -41
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +2191 -3474
- package/dist/hls.js.d.ts +85 -108
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +3136 -3783
- 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 +1260 -1934
- 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 +4182 -5488
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +35 -35
- package/src/config.ts +2 -3
- package/src/controller/abr-controller.ts +20 -24
- package/src/controller/audio-stream-controller.ts +74 -68
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +10 -27
- package/src/controller/base-stream-controller.ts +38 -160
- package/src/controller/buffer-controller.ts +92 -230
- package/src/controller/buffer-operation-queue.ts +19 -16
- package/src/controller/cap-level-controller.ts +2 -3
- package/src/controller/cmcd-controller.ts +14 -51
- package/src/controller/content-steering-controller.ts +15 -29
- package/src/controller/eme-controller.ts +23 -10
- package/src/controller/error-controller.ts +8 -6
- package/src/controller/fps-controller.ts +3 -8
- package/src/controller/fragment-tracker.ts +11 -15
- package/src/controller/gap-controller.ts +16 -43
- package/src/controller/id3-track-controller.ts +7 -7
- package/src/controller/latency-controller.ts +11 -9
- package/src/controller/level-controller.ts +19 -37
- package/src/controller/stream-controller.ts +32 -37
- package/src/controller/subtitle-stream-controller.ts +40 -28
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +21 -19
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +16 -32
- package/src/crypt/fast-aes-key.ts +5 -24
- package/src/demux/audio/aacdemuxer.ts +2 -2
- package/src/demux/audio/ac3-demuxer.ts +3 -4
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/audio/base-audio-demuxer.ts +14 -16
- package/src/demux/audio/mp3demuxer.ts +3 -4
- package/src/demux/audio/mpegaudio.ts +1 -1
- package/src/demux/id3.ts +411 -0
- package/src/demux/mp4demuxer.ts +7 -7
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +12 -4
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +37 -71
- package/src/demux/video/avc-video-parser.ts +119 -208
- package/src/demux/video/base-video-parser.ts +18 -147
- package/src/demux/video/exp-golomb.ts +208 -0
- package/src/events.ts +1 -8
- package/src/exports-named.ts +1 -1
- package/src/hls.ts +38 -61
- package/src/loader/fragment-loader.ts +3 -10
- package/src/loader/key-loader.ts +1 -3
- package/src/loader/level-key.ts +9 -10
- package/src/loader/playlist-loader.ts +5 -4
- package/src/remux/mp4-generator.ts +1 -196
- package/src/remux/mp4-remuxer.ts +8 -24
- package/src/task-loop.ts +2 -5
- package/src/types/component-api.ts +1 -3
- package/src/types/demuxer.ts +0 -4
- package/src/types/events.ts +0 -4
- package/src/types/remuxer.ts +1 -1
- package/src/utils/buffer-helper.ts +31 -12
- package/src/utils/cea-608-parser.ts +3 -1
- package/src/utils/codecs.ts +5 -34
- package/src/utils/fetch-loader.ts +1 -1
- package/src/utils/imsc1-ttml-parser.ts +1 -1
- package/src/utils/keysystem-util.ts +6 -1
- package/src/utils/logger.ts +23 -58
- package/src/utils/mp4-tools.ts +3 -5
- package/src/utils/webvtt-parser.ts +1 -1
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/demux/video/hevc-video-parser.ts +0 -749
- package/src/empty-es.js +0 -5
- package/src/utils/encryption-methods-util.ts +0 -21
- package/src/utils/utf8-utils.ts +0 -18
package/src/hls.ts
CHANGED
@@ -8,7 +8,7 @@ import KeyLoader from './loader/key-loader';
|
|
8
8
|
import StreamController from './controller/stream-controller';
|
9
9
|
import { isMSESupported, isSupported } from './is-supported';
|
10
10
|
import { getMediaSource } from './utils/mediasource-helper';
|
11
|
-
import {
|
11
|
+
import { logger, enableLogs } from './utils/logger';
|
12
12
|
import { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';
|
13
13
|
import { EventEmitter } from 'eventemitter3';
|
14
14
|
import { Events } from './events';
|
@@ -59,13 +59,9 @@ export default class Hls implements HlsEventEmitter {
|
|
59
59
|
*/
|
60
60
|
public readonly userConfig: Partial<HlsConfig>;
|
61
61
|
|
62
|
-
/**
|
63
|
-
* The logger functions used by this player instance, configured on player instantiation.
|
64
|
-
*/
|
65
|
-
public readonly logger: ILogger;
|
66
|
-
|
67
62
|
private coreComponents: ComponentAPI[];
|
68
63
|
private networkControllers: NetworkComponentAPI[];
|
64
|
+
private started: boolean = false;
|
69
65
|
private _emitter: HlsEventEmitter = new EventEmitter();
|
70
66
|
private _autoLevelCapping: number = -1;
|
71
67
|
private _maxHdcpLevel: HdcpLevel = null;
|
@@ -146,19 +142,12 @@ export default class Hls implements HlsEventEmitter {
|
|
146
142
|
* @param userConfig - Configuration options applied over `Hls.DefaultConfig`
|
147
143
|
*/
|
148
144
|
constructor(userConfig: Partial<HlsConfig> = {}) {
|
149
|
-
|
150
|
-
|
151
|
-
'Hls instance',
|
152
|
-
));
|
153
|
-
const config = (this.config = mergeConfig(
|
154
|
-
Hls.DefaultConfig,
|
155
|
-
userConfig,
|
156
|
-
logger,
|
157
|
-
));
|
145
|
+
enableLogs(userConfig.debug || false, 'Hls instance');
|
146
|
+
const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig));
|
158
147
|
this.userConfig = userConfig;
|
159
148
|
|
160
149
|
if (config.progressive) {
|
161
|
-
enableStreamingMode(config
|
150
|
+
enableStreamingMode(config);
|
162
151
|
}
|
163
152
|
|
164
153
|
// core controllers and network loaders
|
@@ -171,10 +160,8 @@ export default class Hls implements HlsEventEmitter {
|
|
171
160
|
} = config;
|
172
161
|
const errorController = new ConfigErrorController(this);
|
173
162
|
const abrController = (this.abrController = new ConfigAbrController(this));
|
174
|
-
// FragmentTracker must be defined before StreamController because the order of event handling is important
|
175
|
-
const fragmentTracker = new FragmentTracker(this);
|
176
163
|
const bufferController = (this.bufferController =
|
177
|
-
new ConfigBufferController(this
|
164
|
+
new ConfigBufferController(this));
|
178
165
|
const capLevelController = (this.capLevelController =
|
179
166
|
new ConfigCapLevelController(this));
|
180
167
|
|
@@ -183,7 +170,7 @@ export default class Hls implements HlsEventEmitter {
|
|
183
170
|
const id3TrackController = new ID3TrackController(this);
|
184
171
|
|
185
172
|
const ConfigContentSteeringController = config.contentSteeringController;
|
186
|
-
//
|
173
|
+
// ConentSteeringController is defined before LevelController to receive Multivariant Playlist events first
|
187
174
|
const contentSteering = ConfigContentSteeringController
|
188
175
|
? new ConfigContentSteeringController(this)
|
189
176
|
: null;
|
@@ -191,6 +178,8 @@ export default class Hls implements HlsEventEmitter {
|
|
191
178
|
this,
|
192
179
|
contentSteering,
|
193
180
|
));
|
181
|
+
// FragmentTracker must be defined before StreamController because the order of event handling is important
|
182
|
+
const fragmentTracker = new FragmentTracker(this);
|
194
183
|
const keyLoader = new KeyLoader(this.config);
|
195
184
|
const streamController = (this.streamController = new StreamController(
|
196
185
|
this,
|
@@ -331,7 +320,7 @@ export default class Hls implements HlsEventEmitter {
|
|
331
320
|
try {
|
332
321
|
return this.emit(event, event, eventObject);
|
333
322
|
} catch (error) {
|
334
|
-
|
323
|
+
logger.error(
|
335
324
|
'An internal error happened while handling event ' +
|
336
325
|
event +
|
337
326
|
'. Error message: "' +
|
@@ -365,7 +354,7 @@ export default class Hls implements HlsEventEmitter {
|
|
365
354
|
* Dispose of the instance
|
366
355
|
*/
|
367
356
|
destroy() {
|
368
|
-
|
357
|
+
logger.log('destroy');
|
369
358
|
this.trigger(Events.DESTROYING, undefined);
|
370
359
|
this.detachMedia();
|
371
360
|
this.removeAllListeners();
|
@@ -388,7 +377,7 @@ export default class Hls implements HlsEventEmitter {
|
|
388
377
|
* Attaches Hls.js to a media element
|
389
378
|
*/
|
390
379
|
attachMedia(media: HTMLMediaElement) {
|
391
|
-
|
380
|
+
logger.log('attachMedia');
|
392
381
|
this._media = media;
|
393
382
|
this.trigger(Events.MEDIA_ATTACHING, { media: media });
|
394
383
|
}
|
@@ -397,7 +386,7 @@ export default class Hls implements HlsEventEmitter {
|
|
397
386
|
* Detach Hls.js from the media
|
398
387
|
*/
|
399
388
|
detachMedia() {
|
400
|
-
|
389
|
+
logger.log('detachMedia');
|
401
390
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
402
391
|
this._media = null;
|
403
392
|
}
|
@@ -418,7 +407,7 @@ export default class Hls implements HlsEventEmitter {
|
|
418
407
|
));
|
419
408
|
this._autoLevelCapping = -1;
|
420
409
|
this._maxHdcpLevel = null;
|
421
|
-
|
410
|
+
logger.log(`loadSource:${loadingSource}`);
|
422
411
|
if (
|
423
412
|
media &&
|
424
413
|
loadedSource &&
|
@@ -439,7 +428,8 @@ export default class Hls implements HlsEventEmitter {
|
|
439
428
|
* Defaults to -1 (None: starts from earliest point)
|
440
429
|
*/
|
441
430
|
startLoad(startPosition: number = -1) {
|
442
|
-
|
431
|
+
logger.log(`startLoad(${startPosition})`);
|
432
|
+
this.started = true;
|
443
433
|
this.networkControllers.forEach((controller) => {
|
444
434
|
controller.startLoad(startPosition);
|
445
435
|
});
|
@@ -449,31 +439,34 @@ export default class Hls implements HlsEventEmitter {
|
|
449
439
|
* Stop loading of any stream data.
|
450
440
|
*/
|
451
441
|
stopLoad() {
|
452
|
-
|
442
|
+
logger.log('stopLoad');
|
443
|
+
this.started = false;
|
453
444
|
this.networkControllers.forEach((controller) => {
|
454
445
|
controller.stopLoad();
|
455
446
|
});
|
456
447
|
}
|
457
448
|
|
458
449
|
/**
|
459
|
-
* Resumes stream controller segment loading
|
450
|
+
* Resumes stream controller segment loading if previously started.
|
460
451
|
*/
|
461
452
|
resumeBuffering() {
|
462
|
-
this.
|
463
|
-
|
464
|
-
controller
|
465
|
-
|
466
|
-
|
453
|
+
if (this.started) {
|
454
|
+
this.networkControllers.forEach((controller) => {
|
455
|
+
if ('fragmentLoader' in controller) {
|
456
|
+
controller.startLoad(-1);
|
457
|
+
}
|
458
|
+
});
|
459
|
+
}
|
467
460
|
}
|
468
461
|
|
469
462
|
/**
|
470
|
-
*
|
463
|
+
* Stops stream controller segment loading without changing 'started' state like stopLoad().
|
471
464
|
* This allows for media buffering to be paused without interupting playlist loading.
|
472
465
|
*/
|
473
466
|
pauseBuffering() {
|
474
467
|
this.networkControllers.forEach((controller) => {
|
475
|
-
if (controller
|
476
|
-
controller.
|
468
|
+
if ('fragmentLoader' in controller) {
|
469
|
+
controller.stopLoad();
|
477
470
|
}
|
478
471
|
});
|
479
472
|
}
|
@@ -482,7 +475,7 @@ export default class Hls implements HlsEventEmitter {
|
|
482
475
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
483
476
|
*/
|
484
477
|
swapAudioCodec() {
|
485
|
-
|
478
|
+
logger.log('swapAudioCodec');
|
486
479
|
this.streamController.swapAudioCodec();
|
487
480
|
}
|
488
481
|
|
@@ -493,7 +486,7 @@ export default class Hls implements HlsEventEmitter {
|
|
493
486
|
* Automatic recovery of media-errors by this process is configurable.
|
494
487
|
*/
|
495
488
|
recoverMediaError() {
|
496
|
-
|
489
|
+
logger.log('recoverMediaError');
|
497
490
|
const media = this._media;
|
498
491
|
this.detachMedia();
|
499
492
|
if (media) {
|
@@ -524,7 +517,7 @@ export default class Hls implements HlsEventEmitter {
|
|
524
517
|
* Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.
|
525
518
|
*/
|
526
519
|
set currentLevel(newLevel: number) {
|
527
|
-
|
520
|
+
logger.log(`set currentLevel:${newLevel}`);
|
528
521
|
this.levelController.manualLevel = newLevel;
|
529
522
|
this.streamController.immediateLevelSwitch();
|
530
523
|
}
|
@@ -543,7 +536,7 @@ export default class Hls implements HlsEventEmitter {
|
|
543
536
|
* @param newLevel - Pass -1 for automatic level selection
|
544
537
|
*/
|
545
538
|
set nextLevel(newLevel: number) {
|
546
|
-
|
539
|
+
logger.log(`set nextLevel:${newLevel}`);
|
547
540
|
this.levelController.manualLevel = newLevel;
|
548
541
|
this.streamController.nextLevelSwitch();
|
549
542
|
}
|
@@ -562,7 +555,7 @@ export default class Hls implements HlsEventEmitter {
|
|
562
555
|
* @param newLevel - Pass -1 for automatic level selection
|
563
556
|
*/
|
564
557
|
set loadLevel(newLevel: number) {
|
565
|
-
|
558
|
+
logger.log(`set loadLevel:${newLevel}`);
|
566
559
|
this.levelController.manualLevel = newLevel;
|
567
560
|
}
|
568
561
|
|
@@ -593,7 +586,7 @@ export default class Hls implements HlsEventEmitter {
|
|
593
586
|
* Sets "first-level", see getter.
|
594
587
|
*/
|
595
588
|
set firstLevel(newLevel: number) {
|
596
|
-
|
589
|
+
logger.log(`set firstLevel:${newLevel}`);
|
597
590
|
this.levelController.firstLevel = newLevel;
|
598
591
|
}
|
599
592
|
|
@@ -618,7 +611,7 @@ export default class Hls implements HlsEventEmitter {
|
|
618
611
|
* (determined from download of first segment)
|
619
612
|
*/
|
620
613
|
set startLevel(newLevel: number) {
|
621
|
-
|
614
|
+
logger.log(`set startLevel:${newLevel}`);
|
622
615
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
623
616
|
if (newLevel !== -1) {
|
624
617
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -693,7 +686,7 @@ export default class Hls implements HlsEventEmitter {
|
|
693
686
|
*/
|
694
687
|
set autoLevelCapping(newLevel: number) {
|
695
688
|
if (this._autoLevelCapping !== newLevel) {
|
696
|
-
|
689
|
+
logger.log(`set autoLevelCapping:${newLevel}`);
|
697
690
|
this._autoLevelCapping = newLevel;
|
698
691
|
this.levelController.checkMaxAutoUpdated();
|
699
692
|
}
|
@@ -802,10 +795,6 @@ export default class Hls implements HlsEventEmitter {
|
|
802
795
|
return this.streamController.getMainFwdBufferInfo();
|
803
796
|
}
|
804
797
|
|
805
|
-
public get maxBufferLength(): number {
|
806
|
-
return this.streamController.maxBufferLength;
|
807
|
-
}
|
808
|
-
|
809
798
|
/**
|
810
799
|
* Find and select the best matching audio track, making a level switch when a Group change is necessary.
|
811
800
|
* Updates `hls.config.audioPreference`. Returns the selected track, or null when no matching track is found.
|
@@ -981,17 +970,6 @@ export default class Hls implements HlsEventEmitter {
|
|
981
970
|
get forceStartLoad(): boolean {
|
982
971
|
return this.streamController.forceStartLoad;
|
983
972
|
}
|
984
|
-
|
985
|
-
/**
|
986
|
-
* ContentSteering pathwayPriority getter/setter
|
987
|
-
*/
|
988
|
-
get pathwayPriority(): string[] | null {
|
989
|
-
return this.levelController.pathwayPriority;
|
990
|
-
}
|
991
|
-
|
992
|
-
set pathwayPriority(pathwayPriority: string[]) {
|
993
|
-
this.levelController.pathwayPriority = pathwayPriority;
|
994
|
-
}
|
995
973
|
}
|
996
974
|
|
997
975
|
export type {
|
@@ -1054,7 +1032,7 @@ export type {
|
|
1054
1032
|
TSDemuxerConfig,
|
1055
1033
|
} from './config';
|
1056
1034
|
export type { MediaKeySessionContext } from './controller/eme-controller';
|
1057
|
-
export type { ILogger
|
1035
|
+
export type { ILogger } from './utils/logger';
|
1058
1036
|
export type {
|
1059
1037
|
PathwayClone,
|
1060
1038
|
SteeringManifest,
|
@@ -1169,7 +1147,6 @@ export type {
|
|
1169
1147
|
ManifestParsedData,
|
1170
1148
|
MediaAttachedData,
|
1171
1149
|
MediaAttachingData,
|
1172
|
-
MediaEndedData,
|
1173
1150
|
NonNativeTextTrack,
|
1174
1151
|
NonNativeTextTracksData,
|
1175
1152
|
SteeringManifestLoadedData,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
2
2
|
import { Fragment } from './fragment';
|
3
|
-
import
|
3
|
+
import {
|
4
4
|
Loader,
|
5
5
|
LoaderConfiguration,
|
6
6
|
FragmentLoaderContext,
|
@@ -336,11 +336,8 @@ function createLoaderContext(
|
|
336
336
|
if (Number.isFinite(start) && Number.isFinite(end)) {
|
337
337
|
let byteRangeStart = start;
|
338
338
|
let byteRangeEnd = end;
|
339
|
-
if (
|
340
|
-
|
341
|
-
isMethodFullSegmentAesCbc(frag.decryptdata?.method)
|
342
|
-
) {
|
343
|
-
// MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
|
339
|
+
if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {
|
340
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
344
341
|
// has the unencrypted size specified in the range.
|
345
342
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
346
343
|
const fragmentLen = end - start;
|
@@ -375,10 +372,6 @@ function createGapLoadError(frag: Fragment, part?: Part): LoadError {
|
|
375
372
|
return new LoadError(errorData);
|
376
373
|
}
|
377
374
|
|
378
|
-
function isMethodFullSegmentAesCbc(method) {
|
379
|
-
return method === 'AES-128' || method === 'AES-256';
|
380
|
-
}
|
381
|
-
|
382
375
|
export class LoadError extends Error {
|
383
376
|
public readonly data: FragLoadFailResult;
|
384
377
|
constructor(data: FragLoadFailResult) {
|
package/src/loader/key-loader.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
2
|
-
import
|
2
|
+
import {
|
3
3
|
LoaderStats,
|
4
4
|
LoaderResponse,
|
5
5
|
LoaderConfiguration,
|
@@ -194,8 +194,6 @@ export default class KeyLoader implements ComponentAPI {
|
|
194
194
|
}
|
195
195
|
return this.loadKeyEME(keyInfo, frag);
|
196
196
|
case 'AES-128':
|
197
|
-
case 'AES-256':
|
198
|
-
case 'AES-256-CTR':
|
199
197
|
return this.loadKeyHTTP(keyInfo, frag);
|
200
198
|
default:
|
201
199
|
return Promise.reject(
|
package/src/loader/level-key.ts
CHANGED
@@ -2,7 +2,6 @@ import {
|
|
2
2
|
changeEndianness,
|
3
3
|
convertDataUriToArrayBytes,
|
4
4
|
} from '../utils/keysystem-util';
|
5
|
-
import { isFullSegmentEncryption } from '../utils/encryption-methods-util';
|
6
5
|
import { KeySystemFormats } from '../utils/mediakeys-helper';
|
7
6
|
import { mp4pssh } from '../utils/mp4-tools';
|
8
7
|
import { logger } from '../utils/logger';
|
@@ -52,14 +51,13 @@ export class LevelKey implements DecryptData {
|
|
52
51
|
this.keyFormatVersions = formatversions;
|
53
52
|
this.iv = iv;
|
54
53
|
this.encrypted = method ? method !== 'NONE' : false;
|
55
|
-
this.isCommonEncryption =
|
56
|
-
this.encrypted && !isFullSegmentEncryption(method);
|
54
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
57
55
|
}
|
58
56
|
|
59
57
|
public isSupported(): boolean {
|
60
58
|
// If it's Segment encryption or No encryption, just select that key system
|
61
59
|
if (this.method) {
|
62
|
-
if (
|
60
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
63
61
|
return true;
|
64
62
|
}
|
65
63
|
if (this.keyFormat === 'identity') {
|
@@ -90,15 +88,16 @@ export class LevelKey implements DecryptData {
|
|
90
88
|
return null;
|
91
89
|
}
|
92
90
|
|
93
|
-
if (
|
91
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
94
92
|
if (typeof sn !== 'number') {
|
95
93
|
// We are fetching decryption data for a initialization segment
|
96
|
-
// If the segment was encrypted with AES-128
|
94
|
+
// If the segment was encrypted with AES-128
|
97
95
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
if (this.method === 'AES-128' && !this.iv) {
|
97
|
+
logger.warn(
|
98
|
+
`missing IV for initialization segment with method="${this.method}" - compliance issue`,
|
99
|
+
);
|
100
|
+
}
|
102
101
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
103
102
|
sn = 0;
|
104
103
|
}
|
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
import { Events } from '../events';
|
10
10
|
import { ErrorDetails, ErrorTypes } from '../errors';
|
11
|
+
import { logger } from '../utils/logger';
|
11
12
|
import M3U8Parser from './m3u8-parser';
|
12
13
|
import type { LevelParsed, VariableMap } from '../types/level';
|
13
14
|
import type {
|
@@ -220,10 +221,10 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
220
221
|
loaderContext.level === context.level
|
221
222
|
) {
|
222
223
|
// same URL can't overlap
|
223
|
-
|
224
|
+
logger.trace('[playlist-loader]: playlist request ongoing');
|
224
225
|
return;
|
225
226
|
}
|
226
|
-
|
227
|
+
logger.log(
|
227
228
|
`[playlist-loader]: aborting previous loader for type: ${context.type}`,
|
228
229
|
);
|
229
230
|
loader.abort();
|
@@ -407,7 +408,7 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
407
408
|
levels[0].audioCodec &&
|
408
409
|
!levels[0].attrs.AUDIO
|
409
410
|
) {
|
410
|
-
|
411
|
+
logger.log(
|
411
412
|
'[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one',
|
412
413
|
);
|
413
414
|
audioTracks.unshift({
|
@@ -554,7 +555,7 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
554
555
|
message += ` id: ${context.id} group-id: "${context.groupId}"`;
|
555
556
|
}
|
556
557
|
const error = new Error(message);
|
557
|
-
|
558
|
+
logger.warn(`[playlist-loader]: ${message}`);
|
558
559
|
let details = ErrorDetails.UNKNOWN;
|
559
560
|
let fatal = false;
|
560
561
|
|
@@ -28,8 +28,6 @@ class MP4 {
|
|
28
28
|
MP4.types = {
|
29
29
|
avc1: [], // codingname
|
30
30
|
avcC: [],
|
31
|
-
hvc1: [],
|
32
|
-
hvcC: [],
|
33
31
|
btrt: [],
|
34
32
|
dinf: [],
|
35
33
|
dref: [],
|
@@ -841,10 +839,8 @@ class MP4 {
|
|
841
839
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
842
840
|
}
|
843
841
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
844
|
-
} else if (track.segmentCodec === 'avc') {
|
845
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
846
842
|
} else {
|
847
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.
|
843
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
848
844
|
}
|
849
845
|
}
|
850
846
|
|
@@ -1127,197 +1123,6 @@ class MP4 {
|
|
1127
1123
|
const result = appendUint8Array(MP4.FTYP, movie);
|
1128
1124
|
return result;
|
1129
1125
|
}
|
1130
|
-
|
1131
|
-
static hvc1(track) {
|
1132
|
-
const ps = track.params;
|
1133
|
-
const units = [track.vps, track.sps, track.pps];
|
1134
|
-
const NALuLengthSize = 4;
|
1135
|
-
const config = new Uint8Array([
|
1136
|
-
0x01,
|
1137
|
-
(ps.general_profile_space << 6) |
|
1138
|
-
(ps.general_tier_flag ? 32 : 0) |
|
1139
|
-
ps.general_profile_idc,
|
1140
|
-
ps.general_profile_compatibility_flags[0],
|
1141
|
-
ps.general_profile_compatibility_flags[1],
|
1142
|
-
ps.general_profile_compatibility_flags[2],
|
1143
|
-
ps.general_profile_compatibility_flags[3],
|
1144
|
-
ps.general_constraint_indicator_flags[0],
|
1145
|
-
ps.general_constraint_indicator_flags[1],
|
1146
|
-
ps.general_constraint_indicator_flags[2],
|
1147
|
-
ps.general_constraint_indicator_flags[3],
|
1148
|
-
ps.general_constraint_indicator_flags[4],
|
1149
|
-
ps.general_constraint_indicator_flags[5],
|
1150
|
-
ps.general_level_idc,
|
1151
|
-
240 | (ps.min_spatial_segmentation_idc >> 8),
|
1152
|
-
255 & ps.min_spatial_segmentation_idc,
|
1153
|
-
252 | ps.parallelismType,
|
1154
|
-
252 | ps.chroma_format_idc,
|
1155
|
-
248 | ps.bit_depth_luma_minus8,
|
1156
|
-
248 | ps.bit_depth_chroma_minus8,
|
1157
|
-
0x00,
|
1158
|
-
parseInt(ps.frame_rate.fps),
|
1159
|
-
(NALuLengthSize - 1) |
|
1160
|
-
(ps.temporal_id_nested << 2) |
|
1161
|
-
(ps.num_temporal_layers << 3) |
|
1162
|
-
(ps.frame_rate.fixed ? 64 : 0),
|
1163
|
-
units.length,
|
1164
|
-
]);
|
1165
|
-
|
1166
|
-
// compute hvcC size in bytes
|
1167
|
-
let length = config.length;
|
1168
|
-
for (let i = 0; i < units.length; i += 1) {
|
1169
|
-
length += 3;
|
1170
|
-
for (let j = 0; j < units[i].length; j += 1) {
|
1171
|
-
length += 2 + units[i][j].length;
|
1172
|
-
}
|
1173
|
-
}
|
1174
|
-
|
1175
|
-
const hvcC = new Uint8Array(length);
|
1176
|
-
hvcC.set(config, 0);
|
1177
|
-
length = config.length;
|
1178
|
-
// append parameter set units: one vps, one or more sps and pps
|
1179
|
-
const iMax = units.length - 1;
|
1180
|
-
for (let i = 0; i < units.length; i += 1) {
|
1181
|
-
hvcC.set(
|
1182
|
-
new Uint8Array([
|
1183
|
-
(32 + i) | (i === iMax ? 128 : 0),
|
1184
|
-
0x00,
|
1185
|
-
units[i].length,
|
1186
|
-
]),
|
1187
|
-
length,
|
1188
|
-
);
|
1189
|
-
length += 3;
|
1190
|
-
for (let j = 0; j < units[i].length; j += 1) {
|
1191
|
-
hvcC.set(
|
1192
|
-
new Uint8Array([units[i][j].length >> 8, units[i][j].length & 255]),
|
1193
|
-
length,
|
1194
|
-
);
|
1195
|
-
length += 2;
|
1196
|
-
hvcC.set(units[i][j], length);
|
1197
|
-
length += units[i][j].length;
|
1198
|
-
}
|
1199
|
-
}
|
1200
|
-
const hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
1201
|
-
const width = track.width;
|
1202
|
-
const height = track.height;
|
1203
|
-
const hSpacing = track.pixelRatio[0];
|
1204
|
-
const vSpacing = track.pixelRatio[1];
|
1205
|
-
|
1206
|
-
return MP4.box(
|
1207
|
-
MP4.types.hvc1,
|
1208
|
-
new Uint8Array([
|
1209
|
-
0x00,
|
1210
|
-
0x00,
|
1211
|
-
0x00, // reserved
|
1212
|
-
0x00,
|
1213
|
-
0x00,
|
1214
|
-
0x00, // reserved
|
1215
|
-
0x00,
|
1216
|
-
0x01, // data_reference_index
|
1217
|
-
0x00,
|
1218
|
-
0x00, // pre_defined
|
1219
|
-
0x00,
|
1220
|
-
0x00, // reserved
|
1221
|
-
0x00,
|
1222
|
-
0x00,
|
1223
|
-
0x00,
|
1224
|
-
0x00,
|
1225
|
-
0x00,
|
1226
|
-
0x00,
|
1227
|
-
0x00,
|
1228
|
-
0x00,
|
1229
|
-
0x00,
|
1230
|
-
0x00,
|
1231
|
-
0x00,
|
1232
|
-
0x00, // pre_defined
|
1233
|
-
(width >> 8) & 0xff,
|
1234
|
-
width & 0xff, // width
|
1235
|
-
(height >> 8) & 0xff,
|
1236
|
-
height & 0xff, // height
|
1237
|
-
0x00,
|
1238
|
-
0x48,
|
1239
|
-
0x00,
|
1240
|
-
0x00, // horizresolution
|
1241
|
-
0x00,
|
1242
|
-
0x48,
|
1243
|
-
0x00,
|
1244
|
-
0x00, // vertresolution
|
1245
|
-
0x00,
|
1246
|
-
0x00,
|
1247
|
-
0x00,
|
1248
|
-
0x00, // reserved
|
1249
|
-
0x00,
|
1250
|
-
0x01, // frame_count
|
1251
|
-
0x12,
|
1252
|
-
0x64,
|
1253
|
-
0x61,
|
1254
|
-
0x69,
|
1255
|
-
0x6c, // dailymotion/hls.js
|
1256
|
-
0x79,
|
1257
|
-
0x6d,
|
1258
|
-
0x6f,
|
1259
|
-
0x74,
|
1260
|
-
0x69,
|
1261
|
-
0x6f,
|
1262
|
-
0x6e,
|
1263
|
-
0x2f,
|
1264
|
-
0x68,
|
1265
|
-
0x6c,
|
1266
|
-
0x73,
|
1267
|
-
0x2e,
|
1268
|
-
0x6a,
|
1269
|
-
0x73,
|
1270
|
-
0x00,
|
1271
|
-
0x00,
|
1272
|
-
0x00,
|
1273
|
-
0x00,
|
1274
|
-
0x00,
|
1275
|
-
0x00,
|
1276
|
-
0x00,
|
1277
|
-
0x00,
|
1278
|
-
0x00,
|
1279
|
-
0x00,
|
1280
|
-
0x00,
|
1281
|
-
0x00,
|
1282
|
-
0x00, // compressorname
|
1283
|
-
0x00,
|
1284
|
-
0x18, // depth = 24
|
1285
|
-
0x11,
|
1286
|
-
0x11,
|
1287
|
-
]), // pre_defined = -1
|
1288
|
-
hvcc,
|
1289
|
-
MP4.box(
|
1290
|
-
MP4.types.btrt,
|
1291
|
-
new Uint8Array([
|
1292
|
-
0x00,
|
1293
|
-
0x1c,
|
1294
|
-
0x9c,
|
1295
|
-
0x80, // bufferSizeDB
|
1296
|
-
0x00,
|
1297
|
-
0x2d,
|
1298
|
-
0xc6,
|
1299
|
-
0xc0, // maxBitrate
|
1300
|
-
0x00,
|
1301
|
-
0x2d,
|
1302
|
-
0xc6,
|
1303
|
-
0xc0,
|
1304
|
-
]),
|
1305
|
-
), // avgBitrate
|
1306
|
-
MP4.box(
|
1307
|
-
MP4.types.pasp,
|
1308
|
-
new Uint8Array([
|
1309
|
-
hSpacing >> 24, // hSpacing
|
1310
|
-
(hSpacing >> 16) & 0xff,
|
1311
|
-
(hSpacing >> 8) & 0xff,
|
1312
|
-
hSpacing & 0xff,
|
1313
|
-
vSpacing >> 24, // vSpacing
|
1314
|
-
(vSpacing >> 16) & 0xff,
|
1315
|
-
(vSpacing >> 8) & 0xff,
|
1316
|
-
vSpacing & 0xff,
|
1317
|
-
]),
|
1318
|
-
),
|
1319
|
-
);
|
1320
|
-
}
|
1321
1126
|
}
|
1322
1127
|
|
1323
1128
|
export default MP4;
|