@amazon/vinyl 3.2.1 → 3.2.3-next.20261001143710
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 +2 -2
- package/dist/index.cjs +98 -43
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +126 -68
- package/dist/index.js.map +3 -3
- package/dist/test/benchmark.es5.js +7 -6
- package/dist/test/benchmark.js +35 -30
- package/dist/test/benchmark.js.map +3 -3
- package/dist/test/integ.es5.js +329 -312
- package/dist/test/integ.js +519 -187
- package/dist/test/integ.js.map +4 -4
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.js +15 -1
- package/dist/types/current/ad/discoverHlsInterstitials.js +13 -1
- package/dist/types/current/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
- package/dist/types/current/drm/DrmControllerImpl.js +11 -1
- package/dist/types/current/drm/commonEme/MsCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/MsCommonEme.js +2 -2
- package/dist/types/current/drm/commonEme/StandardCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/StandardCommonEme.js +3 -2
- package/dist/types/current/drm/commonEme/WebKitCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/WebKitCommonEme.js +2 -2
- package/dist/types/current/drm/dom/MSMediaKeys.d.ts +1 -1
- package/dist/types/current/drm/dom/MSMediaKeys.d.ts.map +1 -1
- package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts +1 -1
- package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts.map +1 -1
- package/dist/types/current/drm/util/extractContentId.js +2 -2
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
- package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
- package/dist/types/current/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/current/streaming/MediaQualityMetadata.d.ts.map +1 -1
- package/dist/types/current/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.js +14 -5
- package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -0
- package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/current/text/discoverDashTextTracks.js +4 -3
- package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
- package/dist/types/current/text/parseWebVtt.js +3 -2
- package/dist/types/current/track/TrackController.d.ts.map +1 -1
- package/dist/types/current/track/TrackController.js +7 -0
- package/dist/types/current/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -1
- package/dist/types/current/track/hls/buildHlsMediaTimeline.d.ts.map +1 -1
- package/dist/types/current/track/hls/buildHlsMediaTimeline.js +10 -2
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +8 -3
- package/dist/types/current/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
- package/dist/types/current/track/mse/MseTrack.js +5 -6
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts3.7/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts3.7/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts3.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts4.1/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts4.1/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts4.1/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts4.7/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts4.7/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts4.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +66 -0
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +29 -2
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
- package/dist/unit/types/current/drm/commonEme/StandardCommonEme.test.js +12 -4
- package/dist/unit/types/current/drm/util/extractContentId.test.js +7 -0
- package/dist/unit/types/current/index.d.ts +1 -0
- package/dist/unit/types/current/index.d.ts.map +1 -1
- package/dist/unit/types/current/index.js +1 -0
- package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
- package/dist/unit/types/current/streaming/MediaQualityMetadata.test.js +8 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +26 -0
- package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +29 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/TextTrack.test.js +12 -0
- package/dist/unit/types/current/text/discoverDashTextTracks.test.js +17 -0
- package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
- package/dist/unit/types/current/track/TrackController.test.js +15 -60
- package/dist/unit/types/current/track/hls/buildHlsMediaTimeline.test.js +22 -0
- package/dist/unit/types/current/track/hls/createUrlHlsManifestProvider.test.js +23 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/docs/CUSTOMIZATION_GUIDE.md +310 -0
- package/package.json +10 -10
- package/docs/DASH_MANIFEST_TRANSFORM_GUIDE.md +0 -236
package/dist/test/integ.js
CHANGED
|
@@ -5832,7 +5832,8 @@
|
|
|
5832
5832
|
return true;
|
|
5833
5833
|
}
|
|
5834
5834
|
/**
|
|
5835
|
-
* Executes a provided function once per each key/value pair in the Map,
|
|
5835
|
+
* Executes a provided function once per each key/value pair in the Map,
|
|
5836
|
+
* ordered from least recently used to most.
|
|
5836
5837
|
*
|
|
5837
5838
|
* @param callback A callback to invoke for every element in the cache.
|
|
5838
5839
|
* @param thisArg Value to use as this when executing callback
|
|
@@ -5877,8 +5878,8 @@
|
|
|
5877
5878
|
let value = void 0;
|
|
5878
5879
|
const memoized = () => {
|
|
5879
5880
|
if (!cached) {
|
|
5880
|
-
cached = true;
|
|
5881
5881
|
value = inner();
|
|
5882
|
+
cached = true;
|
|
5882
5883
|
}
|
|
5883
5884
|
return value;
|
|
5884
5885
|
};
|
|
@@ -5907,9 +5908,9 @@
|
|
|
5907
5908
|
const memoized = (...args) => {
|
|
5908
5909
|
const key = keyProvider(...args);
|
|
5909
5910
|
if (!hasValue || cachedKey !== key) {
|
|
5910
|
-
hasValue = true;
|
|
5911
|
-
cachedKey = key;
|
|
5912
5911
|
cachedValue = inner(...args);
|
|
5912
|
+
cachedKey = key;
|
|
5913
|
+
hasValue = true;
|
|
5913
5914
|
}
|
|
5914
5915
|
return cachedValue;
|
|
5915
5916
|
};
|
|
@@ -5972,7 +5973,8 @@
|
|
|
5972
5973
|
charCode === 13 || // '\r' (carriage return)
|
|
5973
5974
|
charCode === 10;
|
|
5974
5975
|
}
|
|
5975
|
-
var encodedEntitiesRegex = /&(
|
|
5976
|
+
var encodedEntitiesRegex = /&(?:#(?:x([\da-f]+)|(\d+))|(\w+));/gi;
|
|
5977
|
+
var MAX_CODE_POINT = 1114111;
|
|
5976
5978
|
var predefinedDecodeEntities = /* @__PURE__ */ new Map([
|
|
5977
5979
|
["apos", "'"],
|
|
5978
5980
|
["amp", "&"],
|
|
@@ -5981,20 +5983,22 @@
|
|
|
5981
5983
|
["quot", '"']
|
|
5982
5984
|
]);
|
|
5983
5985
|
function decodeEntities(str, namedEntities = predefinedDecodeEntities) {
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
const entityValue = namedEntities.get(entityName.toLowerCase());
|
|
5991
|
-
if (!entityValue) return substring;
|
|
5992
|
-
return entityValue;
|
|
5986
|
+
return str.replace(
|
|
5987
|
+
encodedEntitiesRegex,
|
|
5988
|
+
(substring, hex, decimal, entityName) => {
|
|
5989
|
+
var _a3;
|
|
5990
|
+
if (hex == null && decimal == null) {
|
|
5991
|
+
return (_a3 = namedEntities.get(entityName.toLowerCase())) != null ? _a3 : substring;
|
|
5993
5992
|
}
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5993
|
+
const codePoint = hex != null ? parseInt(hex, 16) : parseInt(decimal, 10);
|
|
5994
|
+
if (codePoint > MAX_CODE_POINT || isSurrogate(codePoint))
|
|
5995
|
+
return substring;
|
|
5996
|
+
return String.fromCodePoint(codePoint);
|
|
5997
|
+
}
|
|
5998
|
+
);
|
|
5999
|
+
}
|
|
6000
|
+
function isSurrogate(codePoint) {
|
|
6001
|
+
return codePoint >= 55296 && codePoint <= 57343;
|
|
5998
6002
|
}
|
|
5999
6003
|
var standardEntityValueToNames = flipMap(predefinedDecodeEntities);
|
|
6000
6004
|
function eqStr(a, b, ignoreCase = false) {
|
|
@@ -8056,7 +8060,11 @@ ${this.lastInitStack}` : "";
|
|
|
8056
8060
|
__publicField(this, "onDownloadSpeedChange", () => {
|
|
8057
8061
|
var _a3;
|
|
8058
8062
|
const downlink = (_a3 = this.deps.networkInformation) == null ? void 0 : _a3.downlink;
|
|
8059
|
-
const estimatedSpeed = downlink ?
|
|
8063
|
+
const estimatedSpeed = downlink ? (
|
|
8064
|
+
// Megabits are decimal, matching the measured `bytes * 8 / seconds`
|
|
8065
|
+
// this estimate is averaged with.
|
|
8066
|
+
downlink * 1e6
|
|
8067
|
+
) : this.options.unknownDownlinkBandwidthEstimate;
|
|
8060
8068
|
updateStatMetrics(
|
|
8061
8069
|
this._metrics.estimatedDownlinkBandwidth,
|
|
8062
8070
|
estimatedSpeed,
|
|
@@ -8546,38 +8554,41 @@ ${this.lastInitStack}` : "";
|
|
|
8546
8554
|
this.dispatch("request", { requestInfo });
|
|
8547
8555
|
let lastResult = null;
|
|
8548
8556
|
let currentTry = 0;
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
this.dispatch("requestAttemptStart", {
|
|
8556
|
-
requestInfo,
|
|
8557
|
-
attemptInfo
|
|
8558
|
-
});
|
|
8559
|
-
lastResult = await this.doRequest(
|
|
8560
|
-
requestInfo,
|
|
8561
|
-
requestOptions,
|
|
8562
|
-
attemptInfo,
|
|
8563
|
-
timeoutController
|
|
8564
|
-
).catch((reason) => {
|
|
8565
|
-
var _a4;
|
|
8566
|
-
const completeInfo = {
|
|
8567
|
-
ok: false,
|
|
8568
|
-
type: ((_a4 = requestOptions.abort) == null ? void 0 : _a4.aborted()) ? "abort" /* ABORT */ : "internal" /* INTERNAL */,
|
|
8569
|
-
requestInfo,
|
|
8570
|
-
reason,
|
|
8571
|
-
willRetry: false,
|
|
8572
|
-
timestamp: Date.now(),
|
|
8573
|
-
retryAfter: null
|
|
8557
|
+
try {
|
|
8558
|
+
do {
|
|
8559
|
+
++currentTry;
|
|
8560
|
+
const attemptInfo = {
|
|
8561
|
+
currentTry,
|
|
8562
|
+
timestamp: Date.now()
|
|
8574
8563
|
};
|
|
8575
|
-
|
|
8576
|
-
|
|
8564
|
+
this.dispatch("requestAttemptStart", {
|
|
8565
|
+
requestInfo,
|
|
8566
|
+
attemptInfo
|
|
8567
|
+
});
|
|
8568
|
+
lastResult = await this.doRequest(
|
|
8569
|
+
requestInfo,
|
|
8570
|
+
requestOptions,
|
|
8571
|
+
attemptInfo,
|
|
8572
|
+
timeoutController
|
|
8573
|
+
).catch((reason) => {
|
|
8574
|
+
var _a4;
|
|
8575
|
+
const completeInfo = {
|
|
8576
|
+
ok: false,
|
|
8577
|
+
type: ((_a4 = requestOptions.abort) == null ? void 0 : _a4.aborted()) ? "abort" /* ABORT */ : "internal" /* INTERNAL */,
|
|
8578
|
+
requestInfo,
|
|
8579
|
+
reason,
|
|
8580
|
+
willRetry: false,
|
|
8581
|
+
timestamp: Date.now(),
|
|
8582
|
+
retryAfter: null
|
|
8583
|
+
};
|
|
8584
|
+
return { info: completeInfo, response: null };
|
|
8585
|
+
});
|
|
8586
|
+
this.reportMetricsEntry(lastResult.info);
|
|
8587
|
+
this.dispatch("requestAttemptComplete", lastResult.info);
|
|
8588
|
+
} while (!lastResult.info.ok && lastResult.info.willRetry);
|
|
8589
|
+
} finally {
|
|
8577
8590
|
timeoutController.dispose();
|
|
8578
|
-
|
|
8579
|
-
this.dispatch("requestAttemptComplete", lastResult.info);
|
|
8580
|
-
} while (!lastResult.info.ok && lastResult.info.willRetry);
|
|
8591
|
+
}
|
|
8581
8592
|
this.dispatch("requestComplete", lastResult.info);
|
|
8582
8593
|
if (lastResult.info.ok) return lastResult.response;
|
|
8583
8594
|
else throw new RequestError(lastResult.response, lastResult.info);
|
|
@@ -8942,6 +8953,13 @@ ${this.lastInitStack}` : "";
|
|
|
8942
8953
|
function bufferToByteArray(buffer) {
|
|
8943
8954
|
return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
8944
8955
|
}
|
|
8956
|
+
function bufferToArrayBuffer(buffer) {
|
|
8957
|
+
if (buffer instanceof ArrayBuffer) return buffer;
|
|
8958
|
+
return buffer.buffer.slice(
|
|
8959
|
+
buffer.byteOffset,
|
|
8960
|
+
buffer.byteOffset + buffer.byteLength
|
|
8961
|
+
);
|
|
8962
|
+
}
|
|
8945
8963
|
function buffersEqual(bufferA, bufferB) {
|
|
8946
8964
|
if (bufferA === bufferB) return true;
|
|
8947
8965
|
if (!bufferA && !bufferB) return true;
|
|
@@ -10268,7 +10286,11 @@ ${this.lastInitStack}` : "";
|
|
|
10268
10286
|
logVerbose(this, "nextAd");
|
|
10269
10287
|
try {
|
|
10270
10288
|
const ad = await adBreakState2.nextAd();
|
|
10271
|
-
if (this.disposed
|
|
10289
|
+
if (this.disposed) return;
|
|
10290
|
+
if (adBreakState2.completedReason) {
|
|
10291
|
+
if (!this.adBreakState) await nextBreak();
|
|
10292
|
+
return;
|
|
10293
|
+
}
|
|
10272
10294
|
if (ad) {
|
|
10273
10295
|
this.startAd(ad);
|
|
10274
10296
|
} else {
|
|
@@ -10402,12 +10424,18 @@ ${this.lastInitStack}` : "";
|
|
|
10402
10424
|
const currProgress = pC.currentTimePercent;
|
|
10403
10425
|
const progressStart = adState.timeStart / pC.duration;
|
|
10404
10426
|
if (!adState.quartile.first && currProgress > 0.25 && progressStart < AD_START_TOLERANCE) {
|
|
10427
|
+
adState.quartile.first = true;
|
|
10428
|
+
logDebug(this, "adFirstQuartile", adState.ad);
|
|
10405
10429
|
this.dispatch("adFirstQuartile", createAdProgressEvent(adState));
|
|
10406
10430
|
}
|
|
10407
10431
|
if (!adState.quartile.midpoint && currProgress > 0.5 && progressStart < 0.25 + AD_START_TOLERANCE) {
|
|
10432
|
+
adState.quartile.midpoint = true;
|
|
10433
|
+
logDebug(this, "adMidpoint", adState.ad);
|
|
10408
10434
|
this.dispatch("adMidpoint", createAdProgressEvent(adState));
|
|
10409
10435
|
}
|
|
10410
10436
|
if (!adState.quartile.third && currProgress > 0.75 && progressStart < 0.5 + AD_START_TOLERANCE) {
|
|
10437
|
+
adState.quartile.third = true;
|
|
10438
|
+
logDebug(this, "adThirdQuartile", adState.ad);
|
|
10411
10439
|
this.dispatch("adThirdQuartile", createAdProgressEvent(adState));
|
|
10412
10440
|
}
|
|
10413
10441
|
}
|
|
@@ -11143,7 +11171,9 @@ ${this.lastInitStack}` : "";
|
|
|
11143
11171
|
(length) => length === validators.length
|
|
11144
11172
|
);
|
|
11145
11173
|
return createDeepValidator(
|
|
11146
|
-
substitute(locale10.tuple, {
|
|
11174
|
+
substitute(locale10.tuple, {
|
|
11175
|
+
value: validators.map((validator) => validator.description).join(", ")
|
|
11176
|
+
}),
|
|
11147
11177
|
(input, options, path) => {
|
|
11148
11178
|
const errors = [];
|
|
11149
11179
|
errors.push(
|
|
@@ -11448,7 +11478,7 @@ ${this.lastInitStack}` : "";
|
|
|
11448
11478
|
};
|
|
11449
11479
|
var _NumberSchema = class _NumberSchema extends ValueSchema {
|
|
11450
11480
|
/**
|
|
11451
|
-
* The base
|
|
11481
|
+
* The base NumberSchema instance validating that the input is a number.
|
|
11452
11482
|
*/
|
|
11453
11483
|
static get base() {
|
|
11454
11484
|
if (this._base == null)
|
|
@@ -11734,7 +11764,7 @@ ${this.lastInitStack}` : "";
|
|
|
11734
11764
|
};
|
|
11735
11765
|
var _StringSchema = class _StringSchema extends ValueSchema {
|
|
11736
11766
|
/**
|
|
11737
|
-
* The base
|
|
11767
|
+
* The base StringSchema instance validating that the input is a string.
|
|
11738
11768
|
*/
|
|
11739
11769
|
static get base() {
|
|
11740
11770
|
if (this._base == null)
|
|
@@ -12515,6 +12545,7 @@ ${this.lastInitStack}` : "";
|
|
|
12515
12545
|
const url = resolveUrl(assetListUrl, baseUrl);
|
|
12516
12546
|
const response = await requestWithRetry(url);
|
|
12517
12547
|
const json = await readResponseBody(response, "json");
|
|
12548
|
+
const assetListBaseUrl = response.url || url;
|
|
12518
12549
|
const assets = (_a3 = json.ASSETS) != null ? _a3 : [];
|
|
12519
12550
|
const ads = assets.map((asset, i) => {
|
|
12520
12551
|
var _a4;
|
|
@@ -12522,7 +12553,14 @@ ${this.lastInitStack}` : "";
|
|
|
12522
12553
|
id: `${rangeId}-${i}`,
|
|
12523
12554
|
startTime,
|
|
12524
12555
|
duration: (_a4 = asset.DURATION) != null ? _a4 : null,
|
|
12525
|
-
|
|
12556
|
+
// Each Asset-Description "URI" MUST be an absolute URI, so the base
|
|
12557
|
+
// only applies to non-conforming lists. As a leniency (not a spec
|
|
12558
|
+
// rule), resolve against the asset list the URI was read from, as
|
|
12559
|
+
// for any relative reference in a retrieved document (RFC 3986
|
|
12560
|
+
// §5.1.3): asset lists are commonly served by an ad server rather
|
|
12561
|
+
// than alongside the playlist.
|
|
12562
|
+
// @see https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-22#appendix-D.2
|
|
12563
|
+
uri: resolveUrl(asset.URI, assetListBaseUrl)
|
|
12526
12564
|
};
|
|
12527
12565
|
});
|
|
12528
12566
|
return { ads, skipControl: parseSkipControl(json["SKIP-CONTROL"]) };
|
|
@@ -12813,7 +12851,7 @@ ${this.lastInitStack}` : "";
|
|
|
12813
12851
|
__publicField(this, "_disposed", false);
|
|
12814
12852
|
__publicField(this, "messageHandler", (event) => {
|
|
12815
12853
|
this.dispatch("message", {
|
|
12816
|
-
message: event.message
|
|
12854
|
+
message: bufferToArrayBuffer(event.message)
|
|
12817
12855
|
});
|
|
12818
12856
|
});
|
|
12819
12857
|
__publicField(this, "errorHandler", () => {
|
|
@@ -12956,11 +12994,7 @@ ${this.lastInitStack}` : "";
|
|
|
12956
12994
|
return "StandardCommonMediaKeySession";
|
|
12957
12995
|
}
|
|
12958
12996
|
generateRequest() {
|
|
12959
|
-
|
|
12960
|
-
return this.session.generateRequest(
|
|
12961
|
-
this.initDataType,
|
|
12962
|
-
initData instanceof ArrayBuffer ? initData : initData.buffer
|
|
12963
|
-
).catch(createDrmErrorHandler());
|
|
12997
|
+
return this.session.generateRequest(this.initDataType, this.initData).catch(createDrmErrorHandler());
|
|
12964
12998
|
}
|
|
12965
12999
|
update(key) {
|
|
12966
13000
|
if (this.disposed) throw new DisposedError();
|
|
@@ -13068,7 +13102,7 @@ ${this.lastInitStack}` : "";
|
|
|
13068
13102
|
__publicField(this, "_disposed", false);
|
|
13069
13103
|
__publicField(this, "messageHandler", (event) => {
|
|
13070
13104
|
this.dispatch("message", {
|
|
13071
|
-
message: event.message
|
|
13105
|
+
message: bufferToArrayBuffer(event.message)
|
|
13072
13106
|
});
|
|
13073
13107
|
});
|
|
13074
13108
|
__publicField(this, "errorHandler", () => {
|
|
@@ -13966,7 +14000,7 @@ ${this.lastInitStack}` : "";
|
|
|
13966
14000
|
|
|
13967
14001
|
// src/drm/util/extractContentId.ts
|
|
13968
14002
|
function extractContentId(initData) {
|
|
13969
|
-
const bufferStr = bufferToUtf16(initData
|
|
14003
|
+
const bufferStr = bufferToUtf16(bufferToArrayBuffer(initData));
|
|
13970
14004
|
const matches = bufferStr.match(/skd:\/\/(.+)$/);
|
|
13971
14005
|
if (!matches) {
|
|
13972
14006
|
throw new ValidationError("No contentId match", ErrorOrigin.MEDIA);
|
|
@@ -14007,6 +14041,7 @@ ${this.lastInitStack}` : "";
|
|
|
14007
14041
|
// src/drm/DrmControllerImpl.ts
|
|
14008
14042
|
var LICENSE_TIMEOUT = 90;
|
|
14009
14043
|
var LICENSE_TIMEOUT_MESSAGE = "License provider timed out after {time}s";
|
|
14044
|
+
var EXCESSIVE_SESSION_COUNT = 20;
|
|
14010
14045
|
var DrmControllerImpl = class extends EventHostImpl {
|
|
14011
14046
|
constructor(deps, options) {
|
|
14012
14047
|
super();
|
|
@@ -14223,6 +14258,13 @@ ${this.lastInitStack}` : "";
|
|
|
14223
14258
|
trackUri
|
|
14224
14259
|
});
|
|
14225
14260
|
this.sessions.push(newSession);
|
|
14261
|
+
logVerbose(this, `total sessions: ${this.sessions.length}`);
|
|
14262
|
+
if (this.sessions.length === EXCESSIVE_SESSION_COUNT + 1) {
|
|
14263
|
+
logWarn(
|
|
14264
|
+
this,
|
|
14265
|
+
`${this.sessions.length} open key sessions exceeds ${EXCESSIVE_SESSION_COUNT}; sessions may be leaking (not closing on track deactivation)`
|
|
14266
|
+
);
|
|
14267
|
+
}
|
|
14226
14268
|
this.dispatch("sessionCreate", {
|
|
14227
14269
|
initDataType: newSession.initDataType,
|
|
14228
14270
|
mimeType: newSession.mimeType
|
|
@@ -14624,20 +14666,21 @@ ${this.lastInitStack}` : "";
|
|
|
14624
14666
|
let abs = Math.abs(value);
|
|
14625
14667
|
const years = Math.floor(abs / Y);
|
|
14626
14668
|
abs -= years * Y;
|
|
14627
|
-
const months = Math.floor(abs
|
|
14669
|
+
const months = Math.floor(abs / M);
|
|
14628
14670
|
const days = Math.floor(abs % M / D);
|
|
14629
14671
|
const hours = Math.floor(abs % D / H);
|
|
14630
14672
|
const minutes = Math.floor(abs % H / I);
|
|
14631
14673
|
const seconds = abs % I;
|
|
14632
|
-
let
|
|
14633
|
-
if (years > 0)
|
|
14634
|
-
if (months > 0)
|
|
14635
|
-
if (days > 0)
|
|
14636
|
-
|
|
14637
|
-
if (hours > 0)
|
|
14638
|
-
if (minutes > 0)
|
|
14639
|
-
if (seconds > 0
|
|
14640
|
-
|
|
14674
|
+
let date = "";
|
|
14675
|
+
if (years > 0) date += `${years}Y`;
|
|
14676
|
+
if (months > 0) date += `${months}M`;
|
|
14677
|
+
if (days > 0) date += `${days}D`;
|
|
14678
|
+
let time = "";
|
|
14679
|
+
if (hours > 0) time += `${hours}H`;
|
|
14680
|
+
if (minutes > 0) time += `${minutes}M`;
|
|
14681
|
+
if (seconds > 0) time += `${roundToNearest(seconds, 1e-3)}S`;
|
|
14682
|
+
if (!date && !time) time = "0S";
|
|
14683
|
+
return `${sign}P${date}${time && `T${time}`}`;
|
|
14641
14684
|
}
|
|
14642
14685
|
|
|
14643
14686
|
// ../vinyl-mpd-parser/src/error/parsingError.ts
|
|
@@ -15221,7 +15264,7 @@ ${this.lastInitStack}` : "";
|
|
|
15221
15264
|
// src/global/environment.ts
|
|
15222
15265
|
var vinylVersion = parseVersion(
|
|
15223
15266
|
/* istanbul ignore next */
|
|
15224
|
-
"3.2.
|
|
15267
|
+
"3.2.2"
|
|
15225
15268
|
);
|
|
15226
15269
|
|
|
15227
15270
|
// src/global/globalRef.ts
|
|
@@ -15715,15 +15758,13 @@ ${this.lastInitStack}` : "";
|
|
|
15715
15758
|
__publicField(this, "_playing", false);
|
|
15716
15759
|
__publicField(this, "_seeking", false);
|
|
15717
15760
|
__publicField(this, "_waiting", false);
|
|
15718
|
-
|
|
15719
|
-
__publicField(this, "_seekId", 0);
|
|
15761
|
+
__publicField(this, "seekAbortSlot", createAbortSlot());
|
|
15720
15762
|
// Stops the stall detector started after the last seek, if any.
|
|
15721
15763
|
__publicField(this, "stopStallDetection", null);
|
|
15722
15764
|
// default user volume (0.0 to 1.0 scale)
|
|
15723
15765
|
__publicField(this, "userVolume", 1);
|
|
15724
15766
|
__publicField(this, "_pendingPlay", null);
|
|
15725
15767
|
__publicField(this, "playAbort", null);
|
|
15726
|
-
__publicField(this, "disposeAbort", new Abort());
|
|
15727
15768
|
__publicField(this, "options");
|
|
15728
15769
|
this.options = __spreadValues(__spreadProps(__spreadValues({}, defaultPlaybackControllerImplOptions), {
|
|
15729
15770
|
minSeekableBuffer: getMinSeekableBufferDefault()
|
|
@@ -15734,8 +15775,7 @@ ${this.lastInitStack}` : "";
|
|
|
15734
15775
|
const { add } = this.disposer;
|
|
15735
15776
|
add(() => {
|
|
15736
15777
|
var _a3;
|
|
15737
|
-
this.
|
|
15738
|
-
this.disposeAbort.dispose();
|
|
15778
|
+
this.seekAbortSlot.abort();
|
|
15739
15779
|
(_a3 = this.stopStallDetection) == null ? void 0 : _a3.call(this);
|
|
15740
15780
|
});
|
|
15741
15781
|
this.domEvents = add(
|
|
@@ -16148,14 +16188,10 @@ ${this.lastInitStack}` : "";
|
|
|
16148
16188
|
async seekTo(time, tolerance = 0.5) {
|
|
16149
16189
|
var _a3;
|
|
16150
16190
|
logDebug(this, `seekTo: ${time}`);
|
|
16151
|
-
const seekId = ++this._seekId;
|
|
16152
16191
|
(_a3 = this.stopStallDetection) == null ? void 0 : _a3.call(this);
|
|
16153
16192
|
this.stopStallDetection = null;
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
logDebug(this, `seekTo: ${time} superseded by a newer seek`);
|
|
16157
|
-
return true;
|
|
16158
|
-
};
|
|
16193
|
+
this.seekAbortSlot.abort();
|
|
16194
|
+
const seekAbort = this.seekAbortSlot.value;
|
|
16159
16195
|
const nextEvent = (type, options) => {
|
|
16160
16196
|
var _a4;
|
|
16161
16197
|
return nextEventAsPromise(this, type, {
|
|
@@ -16163,12 +16199,25 @@ ${this.lastInitStack}` : "";
|
|
|
16163
16199
|
timeoutMessage: `seek timed out on ${type} event after {time}s`,
|
|
16164
16200
|
timeoutOrigin: ErrorOrigin.INTERNAL,
|
|
16165
16201
|
timeoutLevel: "warn" /* WARN */,
|
|
16166
|
-
abort:
|
|
16202
|
+
abort: seekAbort
|
|
16167
16203
|
});
|
|
16168
16204
|
};
|
|
16205
|
+
try {
|
|
16206
|
+
await this.doSeek(time, tolerance, seekAbort, nextEvent);
|
|
16207
|
+
} catch (error) {
|
|
16208
|
+
if (seekAbort.aborted() && !this.disposed) return;
|
|
16209
|
+
throw error;
|
|
16210
|
+
}
|
|
16211
|
+
}
|
|
16212
|
+
/**
|
|
16213
|
+
* The body of a single {@link seekTo} attempt. Extracted so {@link seekTo}
|
|
16214
|
+
* can wrap it with per-seek abort/supersession handling. `seekAbort` is
|
|
16215
|
+
* aborted when a newer seek supersedes this one (or on dispose).
|
|
16216
|
+
* @private
|
|
16217
|
+
*/
|
|
16218
|
+
async doSeek(time, tolerance, seekAbort, nextEvent) {
|
|
16169
16219
|
if (!this.hasMetadata) {
|
|
16170
16220
|
await nextEvent("loadedMetadata");
|
|
16171
|
-
if (superseded()) return;
|
|
16172
16221
|
}
|
|
16173
16222
|
const seekable = this.seekable;
|
|
16174
16223
|
const range = seekable.getRangeAt(
|
|
@@ -16199,7 +16248,7 @@ ${this.lastInitStack}` : "";
|
|
|
16199
16248
|
);
|
|
16200
16249
|
} else {
|
|
16201
16250
|
const nullIfStuck = (error) => {
|
|
16202
|
-
if (this.
|
|
16251
|
+
if (this.disposed) throw error;
|
|
16203
16252
|
return null;
|
|
16204
16253
|
};
|
|
16205
16254
|
const seekOnce = async (reSeeking) => {
|
|
@@ -16213,7 +16262,7 @@ ${this.lastInitStack}` : "";
|
|
|
16213
16262
|
}).catch(nullIfStuck);
|
|
16214
16263
|
};
|
|
16215
16264
|
let seekedEvent = await seekOnce(false);
|
|
16216
|
-
for (let attempt = 0; !
|
|
16265
|
+
for (let attempt = 0; !seekAbort.aborted() && attempt < SEEK_RETRY_LIMIT && (seekedEvent === null || seekedEvent.reason === "seeked" && !closeTo(clampedTime, this.currentTime, tolerance)); attempt++) {
|
|
16217
16266
|
if (seekedEvent === null) void this.media.play().catch(noop);
|
|
16218
16267
|
logDebug(this, `seekTo: re-seeking to ${clampedTime}`);
|
|
16219
16268
|
seekedEvent = await seekOnce(true);
|
|
@@ -16221,7 +16270,7 @@ ${this.lastInitStack}` : "";
|
|
|
16221
16270
|
if ((seekedEvent == null ? void 0 : seekedEvent.reason) === "emptied") {
|
|
16222
16271
|
throw new AbortError();
|
|
16223
16272
|
}
|
|
16224
|
-
if (!this.paused) this.startStallDetection();
|
|
16273
|
+
if (!this.paused && !seekAbort.aborted()) this.startStallDetection();
|
|
16225
16274
|
}
|
|
16226
16275
|
}
|
|
16227
16276
|
/**
|
|
@@ -16777,14 +16826,16 @@ ${this.lastInitStack}` : "";
|
|
|
16777
16826
|
return;
|
|
16778
16827
|
}
|
|
16779
16828
|
const byteLength = streamingSegment.data.byteLength;
|
|
16780
|
-
|
|
16829
|
+
const remaining = byteLength - this.appendOffset;
|
|
16830
|
+
const firstAppend = this.appendOffset === 0;
|
|
16831
|
+
if (remaining > appendSize) {
|
|
16781
16832
|
const newOffset = this.appendOffset + appendSize;
|
|
16782
16833
|
const chunk = streamingSegment.data.slice(
|
|
16783
16834
|
this.appendOffset,
|
|
16784
16835
|
newOffset
|
|
16785
16836
|
);
|
|
16786
16837
|
await sourceBufferController.append(chunk);
|
|
16787
|
-
if (
|
|
16838
|
+
if (firstAppend) {
|
|
16788
16839
|
this.buffered.push(streamingSegment);
|
|
16789
16840
|
}
|
|
16790
16841
|
this.appendOffset = newOffset;
|
|
@@ -16793,9 +16844,13 @@ ${this.lastInitStack}` : "";
|
|
|
16793
16844
|
`appended chunk, this.appendOffset: ${this.appendOffset}`
|
|
16794
16845
|
);
|
|
16795
16846
|
} else {
|
|
16796
|
-
await sourceBufferController.append(
|
|
16797
|
-
|
|
16798
|
-
|
|
16847
|
+
await sourceBufferController.append(
|
|
16848
|
+
firstAppend ? streamingSegment.data : streamingSegment.data.slice(this.appendOffset)
|
|
16849
|
+
);
|
|
16850
|
+
this.appendOffset = byteLength;
|
|
16851
|
+
if (firstAppend) {
|
|
16852
|
+
this.buffered.push(streamingSegment);
|
|
16853
|
+
}
|
|
16799
16854
|
}
|
|
16800
16855
|
if (!tail) this.refreshHead();
|
|
16801
16856
|
}
|
|
@@ -17078,6 +17133,7 @@ ${this.lastInitStack}` : "";
|
|
|
17078
17133
|
this.activateDisposer.dispose();
|
|
17079
17134
|
this.activateDisposer = null;
|
|
17080
17135
|
++this.durationToken;
|
|
17136
|
+
this.durationSet = false;
|
|
17081
17137
|
try {
|
|
17082
17138
|
URL.revokeObjectURL(this.objectUrl);
|
|
17083
17139
|
} catch (error) {
|
|
@@ -17626,6 +17682,7 @@ ${this.lastInitStack}` : "";
|
|
|
17626
17682
|
dispose() {
|
|
17627
17683
|
this._disposed = true;
|
|
17628
17684
|
this.callbacks.length = 0;
|
|
17685
|
+
this.n = 0;
|
|
17629
17686
|
}
|
|
17630
17687
|
notify(value, previousValue) {
|
|
17631
17688
|
this._changeId++;
|
|
@@ -17741,23 +17798,26 @@ ${this.lastInitStack}` : "";
|
|
|
17741
17798
|
providers[key] = provider;
|
|
17742
17799
|
current[key] = provider.value;
|
|
17743
17800
|
}
|
|
17744
|
-
|
|
17801
|
+
let published = __spreadValues({}, current);
|
|
17802
|
+
const publish = (setData) => {
|
|
17803
|
+
published = __spreadValues({}, current);
|
|
17804
|
+
setData(published);
|
|
17805
|
+
};
|
|
17806
|
+
return externalData(published, (setData) => {
|
|
17745
17807
|
const subs = [];
|
|
17808
|
+
let subscribing = true;
|
|
17746
17809
|
for (const key of keys) {
|
|
17747
|
-
const provider = providers[key];
|
|
17748
|
-
let isFirst = true;
|
|
17749
17810
|
subs.push(
|
|
17750
|
-
|
|
17751
|
-
if (isFirst) {
|
|
17752
|
-
isFirst = false;
|
|
17753
|
-
return;
|
|
17754
|
-
}
|
|
17811
|
+
providers[key].onData((value) => {
|
|
17755
17812
|
current[key] = value;
|
|
17756
|
-
|
|
17813
|
+
if (!subscribing) publish(setData);
|
|
17757
17814
|
})
|
|
17758
17815
|
);
|
|
17759
17816
|
}
|
|
17760
|
-
|
|
17817
|
+
subscribing = false;
|
|
17818
|
+
if (keys.some((key) => current[key] !== published[key])) {
|
|
17819
|
+
publish(setData);
|
|
17820
|
+
}
|
|
17761
17821
|
return () => {
|
|
17762
17822
|
for (const unsub of subs) unsub();
|
|
17763
17823
|
};
|
|
@@ -19180,10 +19240,16 @@ ${this.lastInitStack}` : "";
|
|
|
19180
19240
|
return out;
|
|
19181
19241
|
}
|
|
19182
19242
|
function isTextAdaptationSet(adaptationSet) {
|
|
19243
|
+
var _a3;
|
|
19183
19244
|
if (adaptationSet.contentType === "text") return true;
|
|
19184
19245
|
const mt = adaptationSet.mimeType;
|
|
19185
19246
|
if (mt && mt.startsWith("text/")) return true;
|
|
19186
|
-
return
|
|
19247
|
+
return ((_a3 = adaptationSet.Representation) != null ? _a3 : []).some(
|
|
19248
|
+
(representation) => {
|
|
19249
|
+
var _a4;
|
|
19250
|
+
return (_a4 = representation.mimeType) == null ? void 0 : _a4.startsWith("text/");
|
|
19251
|
+
}
|
|
19252
|
+
);
|
|
19187
19253
|
}
|
|
19188
19254
|
function isSidecarTextMime(mimeType) {
|
|
19189
19255
|
if (mimeType == null) return true;
|
|
@@ -19441,7 +19507,7 @@ ${this.lastInitStack}` : "";
|
|
|
19441
19507
|
const cues = [];
|
|
19442
19508
|
const styles = [];
|
|
19443
19509
|
let i = 1;
|
|
19444
|
-
while (i < lines.length && lines[i] !== "") i++;
|
|
19510
|
+
while (i < lines.length && lines[i] !== "" && !lines[i].includes("-->")) i++;
|
|
19445
19511
|
while (i < lines.length) {
|
|
19446
19512
|
if (lines[i] === "") {
|
|
19447
19513
|
i++;
|
|
@@ -20561,7 +20627,6 @@ ${this.lastInitStack}` : "";
|
|
|
20561
20627
|
const deps = depsContainer.dependencies;
|
|
20562
20628
|
super(uri, type, deps);
|
|
20563
20629
|
__publicField(this, "streams", []);
|
|
20564
|
-
__publicField(this, "disposeAbort", new Abort());
|
|
20565
20630
|
__publicField(this, "lastPreloadOptions", null);
|
|
20566
20631
|
__publicField(this, "allFetchedRanges", []);
|
|
20567
20632
|
__publicField(this, "_fetchedRanges", new IntersectionRanges(
|
|
@@ -20586,7 +20651,7 @@ ${this.lastInitStack}` : "";
|
|
|
20586
20651
|
if (this.active) {
|
|
20587
20652
|
this.deps.drmController.initializeForPlayback(event.current, {
|
|
20588
20653
|
trackUri: this.uri,
|
|
20589
|
-
abort: this.
|
|
20654
|
+
abort: this.drmSessionAbort.value
|
|
20590
20655
|
});
|
|
20591
20656
|
}
|
|
20592
20657
|
});
|
|
@@ -20594,7 +20659,7 @@ ${this.lastInitStack}` : "";
|
|
|
20594
20659
|
if (event.current == null) return;
|
|
20595
20660
|
this.deps.drmController.setBufferingDrmInfo(event.current, {
|
|
20596
20661
|
trackUri: this.uri,
|
|
20597
|
-
abort: this.
|
|
20662
|
+
abort: this.drmSessionAbort.value
|
|
20598
20663
|
});
|
|
20599
20664
|
});
|
|
20600
20665
|
add(
|
|
@@ -20832,7 +20897,7 @@ ${this.lastInitStack}` : "";
|
|
|
20832
20897
|
this.streams.forEach((stream) => {
|
|
20833
20898
|
this.deps.drmController.initializeForPlayback(
|
|
20834
20899
|
stream.streamingQuality,
|
|
20835
|
-
{ trackUri: this.uri, abort: this.
|
|
20900
|
+
{ trackUri: this.uri, abort: this.drmSessionAbort.value }
|
|
20836
20901
|
);
|
|
20837
20902
|
});
|
|
20838
20903
|
this.deps.playbackSource.src = this.deps.mediaSourceController.activate();
|
|
@@ -20858,7 +20923,7 @@ ${this.lastInitStack}` : "";
|
|
|
20858
20923
|
this.callOnStreams("deactivate");
|
|
20859
20924
|
this.deps.drmController.setBufferingDrmInfo(null, {
|
|
20860
20925
|
trackUri: this.uri,
|
|
20861
|
-
abort: this.
|
|
20926
|
+
abort: this.drmSessionAbort.value
|
|
20862
20927
|
});
|
|
20863
20928
|
(_b = this.deps.textTrackController) == null ? void 0 : _b.deactivate();
|
|
20864
20929
|
this.deps.playbackSource.src = null;
|
|
@@ -22604,7 +22669,9 @@ ${this.lastInitStack}` : "";
|
|
|
22604
22669
|
audioConfig: null,
|
|
22605
22670
|
videoConfig: null,
|
|
22606
22671
|
audioDecodeTime: 0,
|
|
22607
|
-
videoDecodeTime: 0
|
|
22672
|
+
videoDecodeTime: 0,
|
|
22673
|
+
audioTrackId: null,
|
|
22674
|
+
videoTrackId: null
|
|
22608
22675
|
};
|
|
22609
22676
|
return { transmux: (data2) => transmux(state, data2) };
|
|
22610
22677
|
}
|
|
@@ -22659,11 +22726,12 @@ ${this.lastInitStack}` : "";
|
|
|
22659
22726
|
sampleRate: sampleRate2,
|
|
22660
22727
|
audioSpecificConfig: buildAudioSpecificConfig(firstFrame)
|
|
22661
22728
|
};
|
|
22729
|
+
state.audioTrackId = 1;
|
|
22662
22730
|
buildInitSegment(
|
|
22663
22731
|
state,
|
|
22664
22732
|
moov(
|
|
22665
22733
|
audioTrak({
|
|
22666
|
-
trackId:
|
|
22734
|
+
trackId: state.audioTrackId,
|
|
22667
22735
|
sampleRate: state.audioConfig.sampleRate,
|
|
22668
22736
|
channelCount: state.audioConfig.channelConfiguration,
|
|
22669
22737
|
sampleEntry: mp4aSampleEntry(state.audioConfig)
|
|
@@ -22690,7 +22758,7 @@ ${this.lastInitStack}` : "";
|
|
|
22690
22758
|
const duration = frames.length * samplesPerFrame / sampleRate;
|
|
22691
22759
|
const moofBox = moof({
|
|
22692
22760
|
sequenceNumber: state.sequenceNumber++,
|
|
22693
|
-
trackId:
|
|
22761
|
+
trackId: state.audioTrackId,
|
|
22694
22762
|
baseDecodeTime: state.audioDecodeTime,
|
|
22695
22763
|
samples
|
|
22696
22764
|
});
|
|
@@ -22796,9 +22864,10 @@ ${this.lastInitStack}` : "";
|
|
|
22796
22864
|
if (!state.initSegment && (audioConfig || videoConfig)) {
|
|
22797
22865
|
const traks = [];
|
|
22798
22866
|
if (videoConfig) {
|
|
22867
|
+
state.videoTrackId = traks.length + 1;
|
|
22799
22868
|
traks.push(
|
|
22800
22869
|
videoTrak({
|
|
22801
|
-
trackId:
|
|
22870
|
+
trackId: state.videoTrackId,
|
|
22802
22871
|
width: videoConfig.width,
|
|
22803
22872
|
height: videoConfig.height,
|
|
22804
22873
|
sampleEntry: avc1SampleEntry(videoConfig)
|
|
@@ -22806,9 +22875,10 @@ ${this.lastInitStack}` : "";
|
|
|
22806
22875
|
);
|
|
22807
22876
|
}
|
|
22808
22877
|
if (audioConfig) {
|
|
22878
|
+
state.audioTrackId = traks.length + 1;
|
|
22809
22879
|
traks.push(
|
|
22810
22880
|
audioTrak({
|
|
22811
|
-
trackId:
|
|
22881
|
+
trackId: state.audioTrackId,
|
|
22812
22882
|
sampleRate: audioConfig.sampleRate,
|
|
22813
22883
|
channelCount: audioConfig.channelConfiguration,
|
|
22814
22884
|
sampleEntry: mp4aSampleEntry(audioConfig)
|
|
@@ -22819,8 +22889,8 @@ ${this.lastInitStack}` : "";
|
|
|
22819
22889
|
}
|
|
22820
22890
|
const fragments = [];
|
|
22821
22891
|
let duration = 0;
|
|
22822
|
-
if (videoConfig && videoNalus.length > 0) {
|
|
22823
|
-
const trackId =
|
|
22892
|
+
if (videoConfig && videoNalus.length > 0 && state.videoTrackId != null) {
|
|
22893
|
+
const trackId = state.videoTrackId;
|
|
22824
22894
|
const accessUnits = [];
|
|
22825
22895
|
let pendingParams = [];
|
|
22826
22896
|
for (const nalu of videoNalus) {
|
|
@@ -22887,8 +22957,8 @@ ${this.lastInitStack}` : "";
|
|
|
22887
22957
|
duration = accessUnits.length * frameDuration / MPEG_TIMESCALE;
|
|
22888
22958
|
}
|
|
22889
22959
|
}
|
|
22890
|
-
if (audioConfig && audioRawData && audioFrames.length > 0) {
|
|
22891
|
-
const trackId =
|
|
22960
|
+
if (audioConfig && audioRawData && audioFrames.length > 0 && state.audioTrackId != null) {
|
|
22961
|
+
const trackId = state.audioTrackId;
|
|
22892
22962
|
const samplesPerFrame = 1024;
|
|
22893
22963
|
const samples = [];
|
|
22894
22964
|
const parts = [];
|
|
@@ -23188,7 +23258,11 @@ ${this.lastInitStack}` : "";
|
|
|
23188
23258
|
async getSegment(time, affordance = 0) {
|
|
23189
23259
|
var _a3;
|
|
23190
23260
|
const playlist = await data2.getMediaPlaylist(playlistUri);
|
|
23191
|
-
const playlistBaseUrl =
|
|
23261
|
+
const playlistBaseUrl = getPlaylistBaseUrl(
|
|
23262
|
+
playlist,
|
|
23263
|
+
playlistUri,
|
|
23264
|
+
baseUrl
|
|
23265
|
+
);
|
|
23192
23266
|
const segments = buildSegmentTimeline(
|
|
23193
23267
|
deps,
|
|
23194
23268
|
playlistBaseUrl,
|
|
@@ -23235,9 +23309,13 @@ ${this.lastInitStack}` : "";
|
|
|
23235
23309
|
const variant2 = data2.mainPlaylist.variants[0];
|
|
23236
23310
|
const media = await data2.getMediaPlaylist(variant2.uri);
|
|
23237
23311
|
const contentDuration = media.ended ? media.segments.reduce((sum, s) => sum + s.duration, 0) : null;
|
|
23238
|
-
const playlistBaseUrl =
|
|
23312
|
+
const playlistBaseUrl = getPlaylistBaseUrl(media, variant2.uri, data2.baseUrl);
|
|
23239
23313
|
return discoverHlsInterstitials(media, playlistBaseUrl, contentDuration);
|
|
23240
23314
|
}
|
|
23315
|
+
function getPlaylistBaseUrl(playlist, playlistUri, mainBaseUrl) {
|
|
23316
|
+
var _a3;
|
|
23317
|
+
return (_a3 = playlist.baseUrl) != null ? _a3 : resolveUrl(playlistUri, mainBaseUrl);
|
|
23318
|
+
}
|
|
23241
23319
|
|
|
23242
23320
|
// src/track/hls/createDefaultHlsManifestTransformer.ts
|
|
23243
23321
|
function createDefaultHlsManifestTransformer(deps) {
|
|
@@ -23370,8 +23448,11 @@ ${this.lastInitStack}` : "";
|
|
|
23370
23448
|
const variantUrl = resolveUrl(uri, baseUrl);
|
|
23371
23449
|
const response = await requestWithRetry(variantUrl, requestInit, { abort });
|
|
23372
23450
|
const text = await readResponseBody(response, "text");
|
|
23373
|
-
const
|
|
23374
|
-
|
|
23451
|
+
const playlistUrl = response.url || variantUrl;
|
|
23452
|
+
const queryParams = parseQueryParams(playlistUrl);
|
|
23453
|
+
return __spreadProps(__spreadValues({}, parseMediaPlaylist(text, defines, queryParams)), {
|
|
23454
|
+
baseUrl: playlistUrl
|
|
23455
|
+
});
|
|
23375
23456
|
}
|
|
23376
23457
|
function parseQueryParams(url) {
|
|
23377
23458
|
const queryStart = url.indexOf("?");
|
|
@@ -23823,6 +23904,9 @@ ${this.lastInitStack}` : "";
|
|
|
23823
23904
|
for (const cachedTrack of this.trackCache.values()) {
|
|
23824
23905
|
cachedTrack.clearPrefetch();
|
|
23825
23906
|
}
|
|
23907
|
+
for (const adTracks of this.adTracksByParent.values()) {
|
|
23908
|
+
for (const adTrack of adTracks.values()) adTrack.clearPrefetch();
|
|
23909
|
+
}
|
|
23826
23910
|
}
|
|
23827
23911
|
clearQueue() {
|
|
23828
23912
|
this.setQueue(this._current, []);
|
|
@@ -27294,6 +27378,47 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27294
27378
|
await flush();
|
|
27295
27379
|
expect(c.currentAdBreak).toBeNull();
|
|
27296
27380
|
});
|
|
27381
|
+
it("still enters a pending break when skipped while its ads resolve", async () => {
|
|
27382
|
+
var _a3;
|
|
27383
|
+
const c = createController();
|
|
27384
|
+
let resolveAds = () => void 0;
|
|
27385
|
+
const entered = [];
|
|
27386
|
+
await setContent(
|
|
27387
|
+
c,
|
|
27388
|
+
trackAds(
|
|
27389
|
+
makeBreak({
|
|
27390
|
+
id: "b1",
|
|
27391
|
+
startTime: 0,
|
|
27392
|
+
duration: 30,
|
|
27393
|
+
ads: () => new Promise((resolve) => {
|
|
27394
|
+
resolveAds = resolve;
|
|
27395
|
+
})
|
|
27396
|
+
}),
|
|
27397
|
+
makeBreak({
|
|
27398
|
+
id: "b2",
|
|
27399
|
+
startTime: 1,
|
|
27400
|
+
duration: 30,
|
|
27401
|
+
ads: [
|
|
27402
|
+
{
|
|
27403
|
+
id: "a2",
|
|
27404
|
+
startTime: 1,
|
|
27405
|
+
duration: 10,
|
|
27406
|
+
uri: "ad2.m3u8"
|
|
27407
|
+
}
|
|
27408
|
+
]
|
|
27409
|
+
})
|
|
27410
|
+
)
|
|
27411
|
+
);
|
|
27412
|
+
c.on("adBreakEntered", (e) => entered.push(e.adBreak.id));
|
|
27413
|
+
updateTime(2);
|
|
27414
|
+
await flush();
|
|
27415
|
+
expect(entered).toEqual(["b1"]);
|
|
27416
|
+
c.skipAdBreak();
|
|
27417
|
+
resolveAds([]);
|
|
27418
|
+
await flush();
|
|
27419
|
+
expect(entered).toEqual(["b1", "b2"]);
|
|
27420
|
+
expect((_a3 = c.currentAdBreak) == null ? void 0 : _a3.id).toBe("b2");
|
|
27421
|
+
});
|
|
27297
27422
|
});
|
|
27298
27423
|
describe("a break with no ads", () => {
|
|
27299
27424
|
it("completes immediately with a resume position and plays no ad", async () => {
|
|
@@ -27574,6 +27699,35 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27574
27699
|
await flush();
|
|
27575
27700
|
expect(thirds).toEqual(["a1"]);
|
|
27576
27701
|
});
|
|
27702
|
+
it("dispatches each quartile at most once per ad", async () => {
|
|
27703
|
+
const c = createController();
|
|
27704
|
+
const events = [];
|
|
27705
|
+
c.on("adFirstQuartile", () => events.push("first"));
|
|
27706
|
+
c.on("adMidpoint", () => events.push("mid"));
|
|
27707
|
+
c.on("adThirdQuartile", () => events.push("third"));
|
|
27708
|
+
await setContent(
|
|
27709
|
+
c,
|
|
27710
|
+
trackAds(makeBreak({ startTime: 0, duration: 10 }))
|
|
27711
|
+
);
|
|
27712
|
+
updateTime(0);
|
|
27713
|
+
await flush();
|
|
27714
|
+
playbackController.dispatch("playing", {});
|
|
27715
|
+
playbackController.duration = 10;
|
|
27716
|
+
playbackController.playbackRate = 1;
|
|
27717
|
+
for (const [percent, time] of [
|
|
27718
|
+
[0.3, 3],
|
|
27719
|
+
[0.4, 4],
|
|
27720
|
+
[0.6, 6],
|
|
27721
|
+
[0.7, 7],
|
|
27722
|
+
[0.8, 8],
|
|
27723
|
+
[0.9, 9]
|
|
27724
|
+
]) {
|
|
27725
|
+
playbackController.currentTimePercent = percent;
|
|
27726
|
+
updateTime(time);
|
|
27727
|
+
await flush();
|
|
27728
|
+
}
|
|
27729
|
+
expect(events).toEqual(["first", "mid", "third"]);
|
|
27730
|
+
});
|
|
27577
27731
|
it("does not emit quartiles or throw when the ad duration is zero", async () => {
|
|
27578
27732
|
const c = createController();
|
|
27579
27733
|
const events = [];
|
|
@@ -28617,8 +28771,9 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28617
28771
|
clientAttributes: {}
|
|
28618
28772
|
}, overrides);
|
|
28619
28773
|
}
|
|
28620
|
-
function okJsonResponse(body) {
|
|
28774
|
+
function okJsonResponse(body, url = "") {
|
|
28621
28775
|
return {
|
|
28776
|
+
url,
|
|
28622
28777
|
ok: true,
|
|
28623
28778
|
status: 200,
|
|
28624
28779
|
headers: { get: () => null },
|
|
@@ -28787,7 +28942,7 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28787
28942
|
"https://example.com/ads.json"
|
|
28788
28943
|
);
|
|
28789
28944
|
expect(ads.length).toBe(2);
|
|
28790
|
-
expect(ads[0].uri).toBe("https://
|
|
28945
|
+
expect(ads[0].uri).toBe("https://example.com/mid1.m3u8");
|
|
28791
28946
|
expect(ads[0].duration).toBe(10);
|
|
28792
28947
|
expect(ads[1].uri).toBe("https://cdn.example.com/mid2.m3u8");
|
|
28793
28948
|
expect(ads[1].duration).toBeNull();
|
|
@@ -28795,6 +28950,33 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28795
28950
|
globalThis.fetch = origFetch;
|
|
28796
28951
|
}
|
|
28797
28952
|
});
|
|
28953
|
+
it("resolves relative asset URIs against the redirected asset list URL", async () => {
|
|
28954
|
+
const origFetch = globalThis.fetch;
|
|
28955
|
+
const fetchSpy = jasmine.createSpy("fetch").and.resolveTo(
|
|
28956
|
+
okJsonResponse(
|
|
28957
|
+
{ ASSETS: [{ URI: "mid1.m3u8" }] },
|
|
28958
|
+
"https://ads.example.net/v2/ads.json"
|
|
28959
|
+
)
|
|
28960
|
+
);
|
|
28961
|
+
globalThis.fetch = fetchSpy;
|
|
28962
|
+
try {
|
|
28963
|
+
const playlist = makePlaylist({
|
|
28964
|
+
dateRanges: [
|
|
28965
|
+
makeRange({
|
|
28966
|
+
duration: 10,
|
|
28967
|
+
clientAttributes: {
|
|
28968
|
+
"X-ASSET-LIST": "https://example.com/redirected.json"
|
|
28969
|
+
}
|
|
28970
|
+
})
|
|
28971
|
+
]
|
|
28972
|
+
});
|
|
28973
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
28974
|
+
const ads = await resolveValueProvider(breaks[0].ads);
|
|
28975
|
+
expect(ads[0].uri).toBe("https://ads.example.net/v2/mid1.m3u8");
|
|
28976
|
+
} finally {
|
|
28977
|
+
globalThis.fetch = origFetch;
|
|
28978
|
+
}
|
|
28979
|
+
});
|
|
28798
28980
|
it("caches the X-ASSET-LIST fetch across calls", async () => {
|
|
28799
28981
|
const origFetch = globalThis.fetch;
|
|
28800
28982
|
const fetchSpy = jasmine.createSpy("fetch").and.resolveTo(okJsonResponse({ ASSETS: [{ URI: "x.m3u8" }] }));
|
|
@@ -30172,10 +30354,10 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
30172
30354
|
});
|
|
30173
30355
|
});
|
|
30174
30356
|
describe("when created", () => {
|
|
30175
|
-
it("calls session.generateRequest() with the initData
|
|
30357
|
+
it("calls session.generateRequest() with the initData", () => {
|
|
30176
30358
|
expect(
|
|
30177
30359
|
mediaKeySession.generateRequest
|
|
30178
|
-
).toHaveBeenCalledOnceWith("cenc", initData
|
|
30360
|
+
).toHaveBeenCalledOnceWith("cenc", initData);
|
|
30179
30361
|
mediaKeySession.generateRequest.calls.reset();
|
|
30180
30362
|
const arrayBuffer = new ArrayBuffer(0);
|
|
30181
30363
|
standardCommonMediaKeySession = new StandardCommonMediaKeySession(
|
|
@@ -30188,6 +30370,21 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
30188
30370
|
mediaKeySession.generateRequest
|
|
30189
30371
|
).toHaveBeenCalledOnceWith("cenc", arrayBuffer);
|
|
30190
30372
|
});
|
|
30373
|
+
it("passes only the bytes an offset initData view spans", () => {
|
|
30374
|
+
mediaKeySession.generateRequest.calls.reset();
|
|
30375
|
+
const view = new Uint8Array([1, 2, 3, 4, 5]).subarray(1, 4);
|
|
30376
|
+
standardCommonMediaKeySession = new StandardCommonMediaKeySession(
|
|
30377
|
+
mediaKeySession,
|
|
30378
|
+
mimeType,
|
|
30379
|
+
"cenc",
|
|
30380
|
+
view
|
|
30381
|
+
);
|
|
30382
|
+
const [, passed] = mediaKeySession.generateRequest.calls.mostRecent().args;
|
|
30383
|
+
expectIterableEquals(
|
|
30384
|
+
new Uint8Array(bufferToArrayBuffer(passed)),
|
|
30385
|
+
[2, 3, 4]
|
|
30386
|
+
);
|
|
30387
|
+
});
|
|
30191
30388
|
describe("when session.generateRequest rejects", () => {
|
|
30192
30389
|
it("emits an error event", async () => {
|
|
30193
30390
|
mediaKeySession.generateRequest.and.rejectWith(
|
|
@@ -32139,6 +32336,23 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
32139
32336
|
expect(drmController.isEmeSupported()).toBeFalse();
|
|
32140
32337
|
});
|
|
32141
32338
|
});
|
|
32339
|
+
describe("excessive sessions", () => {
|
|
32340
|
+
it("warns once when the open session count exceeds the threshold", async () => {
|
|
32341
|
+
drmController.setBufferingDrmInfo(drmInfo);
|
|
32342
|
+
for (let i = 0; i < EXCESSIVE_SESSION_COUNT; i++) {
|
|
32343
|
+
await emitEncrypted(new Uint8Array([i]));
|
|
32344
|
+
}
|
|
32345
|
+
expect(drmController.activeSessions).toBe(EXCESSIVE_SESSION_COUNT);
|
|
32346
|
+
expect(logger.value.warn).not.toHaveBeenCalled();
|
|
32347
|
+
await emitEncrypted(new Uint8Array([EXCESSIVE_SESSION_COUNT]));
|
|
32348
|
+
expect(drmController.activeSessions).toBe(
|
|
32349
|
+
EXCESSIVE_SESSION_COUNT + 1
|
|
32350
|
+
);
|
|
32351
|
+
expect(logger.value.warn).toHaveBeenCalledTimes(1);
|
|
32352
|
+
await emitEncrypted(new Uint8Array([EXCESSIVE_SESSION_COUNT + 1]));
|
|
32353
|
+
expect(logger.value.warn).toHaveBeenCalledTimes(1);
|
|
32354
|
+
});
|
|
32355
|
+
});
|
|
32142
32356
|
describe("closeSessions", () => {
|
|
32143
32357
|
it("clears active sessions", async () => {
|
|
32144
32358
|
const sessionCloseSpy = createEventSpy(
|
|
@@ -32628,6 +32842,13 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
32628
32842
|
).toBe("example0");
|
|
32629
32843
|
});
|
|
32630
32844
|
});
|
|
32845
|
+
describe("with an offset view", () => {
|
|
32846
|
+
it("reads only the bytes the view spans", () => {
|
|
32847
|
+
const padded = createContentIdByteArray("\0\0skd://example0\0\0");
|
|
32848
|
+
const view = padded.subarray(4, padded.byteLength - 4);
|
|
32849
|
+
expect(extractContentId(view)).toBe("example0");
|
|
32850
|
+
});
|
|
32851
|
+
});
|
|
32631
32852
|
describe("without match", () => {
|
|
32632
32853
|
it("throws ValidationError", () => {
|
|
32633
32854
|
expect(() => {
|
|
@@ -34107,6 +34328,13 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
34107
34328
|
await clock.tick(controller.options.seekTimeout);
|
|
34108
34329
|
await seekExpectation;
|
|
34109
34330
|
});
|
|
34331
|
+
it("resolves a superseded seek at once when its seeking event never fires", async () => {
|
|
34332
|
+
setSeekable([[0, 100]]);
|
|
34333
|
+
const first2 = controller.seekTo(50);
|
|
34334
|
+
const second = controller.seekTo(60);
|
|
34335
|
+
await expectAsync(first2).toBeResolved();
|
|
34336
|
+
second.catch(() => void 0);
|
|
34337
|
+
});
|
|
34110
34338
|
it("times out pending seeks after seekTimeout", async () => {
|
|
34111
34339
|
const pendingSeekExpectation = expectAsync(
|
|
34112
34340
|
controller.seekTo(60)
|
|
@@ -35914,6 +36142,24 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
35914
36142
|
expect(sourceBufferController.append).toHaveBeenCalledTimes(1);
|
|
35915
36143
|
});
|
|
35916
36144
|
});
|
|
36145
|
+
describe("when the append budget grows while a segment is partly appended", () => {
|
|
36146
|
+
it("appends only the bytes remaining in the segment", async () => {
|
|
36147
|
+
bufferingController.dispose();
|
|
36148
|
+
bufferingController = createBufferingController({
|
|
36149
|
+
maxAppendSize: { audio: 500 },
|
|
36150
|
+
minBuffer: 6
|
|
36151
|
+
});
|
|
36152
|
+
bufferingController.activate();
|
|
36153
|
+
setSegmentList([200, 400]);
|
|
36154
|
+
await open();
|
|
36155
|
+
await setTime(5);
|
|
36156
|
+
expect(getMostRecentAppendData().byteLength).toBe(300);
|
|
36157
|
+
sourceBufferController.append.calls.reset();
|
|
36158
|
+
await setTime(15.5);
|
|
36159
|
+
const appended = sourceBufferController.append.calls.allArgs().map(([data2]) => data2.byteLength);
|
|
36160
|
+
expect(appended[0]).toBe(100);
|
|
36161
|
+
});
|
|
36162
|
+
});
|
|
35917
36163
|
describe("when contentType is undefined", () => {
|
|
35918
36164
|
it("uses DEFAULT_MAX_APPEND_SIZE for max byte length", async () => {
|
|
35919
36165
|
setSegmentList(
|
|
@@ -36675,6 +36921,28 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
36675
36921
|
);
|
|
36676
36922
|
expect(() => controller.deactivate()).not.toThrow();
|
|
36677
36923
|
});
|
|
36924
|
+
it("does not report a re-activated media source as ready to append", async () => {
|
|
36925
|
+
open();
|
|
36926
|
+
await flushPromises();
|
|
36927
|
+
const firstRef = controller.createSourceBuffer("audio", "audio/mp4");
|
|
36928
|
+
expect(controller.readyToAppend).withContext("ready on the first media source").toBeTrue();
|
|
36929
|
+
firstRef.dispose();
|
|
36930
|
+
controller.deactivate();
|
|
36931
|
+
const secondSource = new MockMediaSource();
|
|
36932
|
+
implementEventFakes(secondSource);
|
|
36933
|
+
secondSource.addSourceBuffer.and.callFake(
|
|
36934
|
+
() => new MockSourceBuffer()
|
|
36935
|
+
);
|
|
36936
|
+
mediaSourceFactory.and.returnValue(secondSource);
|
|
36937
|
+
controller.activate();
|
|
36938
|
+
await flushPromises();
|
|
36939
|
+
controller.createSourceBuffer("audio", "audio/mp4");
|
|
36940
|
+
expect(controller.readyToAppend).withContext("duration not yet set on the new media source").toBeFalse();
|
|
36941
|
+
secondSource.readyState = "open";
|
|
36942
|
+
secondSource.dispatchEvent(mockEvent("sourceopen"));
|
|
36943
|
+
await flushPromises();
|
|
36944
|
+
expect(controller.readyToAppend).withContext("ready once the new duration is set").toBeTrue();
|
|
36945
|
+
});
|
|
36678
36946
|
});
|
|
36679
36947
|
describe("duration", () => {
|
|
36680
36948
|
it("sets media source duration after sourceopen", async () => {
|
|
@@ -38437,6 +38705,11 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
38437
38705
|
expect(drmProtectionValidator.isValid({ keySystem: 123 })).toBeFalse();
|
|
38438
38706
|
});
|
|
38439
38707
|
});
|
|
38708
|
+
describe("ALL_CONTENT_TYPES", () => {
|
|
38709
|
+
it("provides a comprehensive list of all content types", () => {
|
|
38710
|
+
expectTypeStrictlyEquals(true);
|
|
38711
|
+
});
|
|
38712
|
+
});
|
|
38440
38713
|
|
|
38441
38714
|
// test/unit/streaming/MediaTimeline.test.ts
|
|
38442
38715
|
describe("getMediaPeriodAtTime", () => {
|
|
@@ -39217,6 +39490,16 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
39217
39490
|
abort: any14(Abort)
|
|
39218
39491
|
});
|
|
39219
39492
|
});
|
|
39493
|
+
it("aborts the drm session abort so key sessions close", async () => {
|
|
39494
|
+
track2 = createTrack();
|
|
39495
|
+
await awaitContentTypes();
|
|
39496
|
+
getAudioStream().streamingQuality = createEmptyMediaQualityMetadata();
|
|
39497
|
+
track2.activate({});
|
|
39498
|
+
const { abort } = deps.drmController.initializeForPlayback.calls.mostRecent().args[1];
|
|
39499
|
+
expect(abort.aborted()).toBeFalse();
|
|
39500
|
+
track2.deactivate();
|
|
39501
|
+
expect(abort.aborted()).toBeTrue();
|
|
39502
|
+
});
|
|
39220
39503
|
});
|
|
39221
39504
|
describe("error", () => {
|
|
39222
39505
|
it("returns the first emitted error", async () => {
|
|
@@ -41183,6 +41466,18 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
41183
41466
|
expect(result.length).toBe(1);
|
|
41184
41467
|
expect(result[0].language).toBe("es");
|
|
41185
41468
|
});
|
|
41469
|
+
it("discovers a text AdaptationSet by its Representation mimeType", () => {
|
|
41470
|
+
const m = manifest3(`
|
|
41471
|
+
<AdaptationSet lang="fr">
|
|
41472
|
+
<Representation id="fr-sub" mimeType="text/vtt" bandwidth="100">
|
|
41473
|
+
<BaseURL>fr.vtt</BaseURL>
|
|
41474
|
+
</Representation>
|
|
41475
|
+
</AdaptationSet>`);
|
|
41476
|
+
const result = discoverDashTextTracks(m, baseUrl);
|
|
41477
|
+
expect(result.length).toBe(1);
|
|
41478
|
+
expect(result[0].language).toBe("fr");
|
|
41479
|
+
expect(result[0].uri).toBe("https://example.com/dash/fr.vtt");
|
|
41480
|
+
});
|
|
41186
41481
|
it("classifies kind=captions when role=caption is set", () => {
|
|
41187
41482
|
const m = manifest3(`
|
|
41188
41483
|
<AdaptationSet contentType="text" lang="en" mimeType="text/vtt">
|
|
@@ -41237,6 +41532,10 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
41237
41532
|
</AdaptationSet>`);
|
|
41238
41533
|
expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
|
|
41239
41534
|
});
|
|
41535
|
+
it("skips a non-text AdaptationSet with no Representation", () => {
|
|
41536
|
+
const m = manifest3(`<AdaptationSet contentType="audio"/>`);
|
|
41537
|
+
expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
|
|
41538
|
+
});
|
|
41240
41539
|
it("skips text AdaptationSets carrying segmented codecs (stpp/wvtt)", () => {
|
|
41241
41540
|
const m = manifest3(`
|
|
41242
41541
|
<AdaptationSet contentType="text" mimeType="application/mp4" codecs="stpp">
|
|
@@ -42268,6 +42567,29 @@ hi`;
|
|
|
42268
42567
|
expect(cues.length).toBe(1);
|
|
42269
42568
|
expect(cues[0].text).toBe("hi");
|
|
42270
42569
|
});
|
|
42570
|
+
it("parses a cue that follows the signature with no blank line", () => {
|
|
42571
|
+
const text = `WEBVTT
|
|
42572
|
+
00:00:01.000 --> 00:00:02.000
|
|
42573
|
+
hi
|
|
42574
|
+
|
|
42575
|
+
00:00:03.000 --> 00:00:04.000
|
|
42576
|
+
there`;
|
|
42577
|
+
const cues = parseWebVtt(text).cues;
|
|
42578
|
+
expect(cues.length).toBe(2);
|
|
42579
|
+
expect(cues[0].startTime).toBe(1);
|
|
42580
|
+
expect(cues[0].text).toBe("hi");
|
|
42581
|
+
expect(cues[1].text).toBe("there");
|
|
42582
|
+
});
|
|
42583
|
+
it("keeps header lines as header when a cue follows with no blank line", () => {
|
|
42584
|
+
const text = `WEBVTT
|
|
42585
|
+
Kind: captions
|
|
42586
|
+
00:00:01.000 --> 00:00:02.000
|
|
42587
|
+
hi`;
|
|
42588
|
+
const cues = parseWebVtt(text).cues;
|
|
42589
|
+
expect(cues.length).toBe(1);
|
|
42590
|
+
expect(cues[0].id).toBeNull();
|
|
42591
|
+
expect(cues[0].text).toBe("hi");
|
|
42592
|
+
});
|
|
42271
42593
|
it("handles trailing identifier without timing line", () => {
|
|
42272
42594
|
const text = `WEBVTT
|
|
42273
42595
|
|
|
@@ -43657,6 +43979,13 @@ x`);
|
|
|
43657
43979
|
});
|
|
43658
43980
|
});
|
|
43659
43981
|
|
|
43982
|
+
// test/unit/text/TextTrack.test.ts
|
|
43983
|
+
describe("ALL_TEXT_TRACK_EVENTS", () => {
|
|
43984
|
+
it("provides a comprehensive list of all text track events", () => {
|
|
43985
|
+
expectTypeStrictlyEquals(true);
|
|
43986
|
+
});
|
|
43987
|
+
});
|
|
43988
|
+
|
|
43660
43989
|
// test/unit/text/VttCueStyle.test.ts
|
|
43661
43990
|
describe("VttCueStyle", () => {
|
|
43662
43991
|
describe("isVttCue", () => {
|
|
@@ -48763,6 +49092,29 @@ x`);
|
|
|
48763
49092
|
);
|
|
48764
49093
|
fetchSpy.and.callThrough();
|
|
48765
49094
|
});
|
|
49095
|
+
it("resolves segment and map URIs against the media playlist baseUrl", async () => {
|
|
49096
|
+
const variant2 = createVariant("v1.m3u8", 128e3);
|
|
49097
|
+
const playlist = __spreadProps(__spreadValues({}, createMediaPlaylist([10])), {
|
|
49098
|
+
// The media playlist was redirected away from the main playlist's
|
|
49099
|
+
// directory.
|
|
49100
|
+
baseUrl: "https://redirect.example.net/hls/v1.m3u8"
|
|
49101
|
+
});
|
|
49102
|
+
const manifestData2 = createManifestData([variant2], playlist);
|
|
49103
|
+
const fetchSpy = spyOn(globalThis, "fetch").and.callFake(
|
|
49104
|
+
() => Promise.resolve(new Response(new ArrayBuffer(100)))
|
|
49105
|
+
);
|
|
49106
|
+
const timeline = buildHlsMediaTimeline(deps, manifestData2);
|
|
49107
|
+
const quality = timeline.periods[0].qualities[0];
|
|
49108
|
+
const segment = await quality.getSegment(5);
|
|
49109
|
+
await segment.initData();
|
|
49110
|
+
await segment.data();
|
|
49111
|
+
const urls = fetchSpy.calls.allArgs().map(([input]) => String(input));
|
|
49112
|
+
expect(urls).toEqual([
|
|
49113
|
+
"https://redirect.example.net/hls/init.mp4",
|
|
49114
|
+
"https://redirect.example.net/hls/seg0.m4s"
|
|
49115
|
+
]);
|
|
49116
|
+
fetchSpy.and.callThrough();
|
|
49117
|
+
});
|
|
48766
49118
|
it("getDuration throws when no variants", async () => {
|
|
48767
49119
|
const manifestData2 = createManifestData([], createMediaPlaylist([]));
|
|
48768
49120
|
const timeline = buildHlsMediaTimeline(deps, manifestData2);
|
|
@@ -49440,6 +49792,29 @@ x`);
|
|
|
49440
49792
|
"https://example.com/path/audio.m3u8"
|
|
49441
49793
|
);
|
|
49442
49794
|
});
|
|
49795
|
+
it("sets the baseUrl from the response URL", async () => {
|
|
49796
|
+
mockRequester.request.and.callFake(() => {
|
|
49797
|
+
const resp = new Response(mediaM3u8);
|
|
49798
|
+
Object.defineProperty(resp, "url", {
|
|
49799
|
+
value: "https://redirected.com/hls/audio.m3u8"
|
|
49800
|
+
});
|
|
49801
|
+
return Promise.resolve(resp);
|
|
49802
|
+
});
|
|
49803
|
+
const playlist = await fetchMediaPlaylist({
|
|
49804
|
+
uri: "audio.m3u8",
|
|
49805
|
+
baseUrl: "https://example.com/path/main.m3u8",
|
|
49806
|
+
defines: void 0
|
|
49807
|
+
});
|
|
49808
|
+
expect(playlist.baseUrl).toBe("https://redirected.com/hls/audio.m3u8");
|
|
49809
|
+
});
|
|
49810
|
+
it("falls back to the requested URL when the response has no URL", async () => {
|
|
49811
|
+
const playlist = await fetchMediaPlaylist({
|
|
49812
|
+
uri: "audio.m3u8",
|
|
49813
|
+
baseUrl: "https://example.com/path/main.m3u8",
|
|
49814
|
+
defines: void 0
|
|
49815
|
+
});
|
|
49816
|
+
expect(playlist.baseUrl).toBe("https://example.com/path/audio.m3u8");
|
|
49817
|
+
});
|
|
49443
49818
|
it("resolves EXT-X-DEFINE:QUERYPARAM from the playlist URL query string", async () => {
|
|
49444
49819
|
mockRequester.request.and.callFake(
|
|
49445
49820
|
() => Promise.resolve(
|
|
@@ -52073,49 +52448,6 @@ x`);
|
|
|
52073
52448
|
expect(track2.clearPrefetch).toHaveBeenCalledTimes(1);
|
|
52074
52449
|
}
|
|
52075
52450
|
});
|
|
52076
|
-
it("also clears prefetch on preloaded ad tracks", async () => {
|
|
52077
|
-
pending(
|
|
52078
|
-
"REVIEW: the refactor no longer proactively preloads ad tracks discovered on the current track (ad tracks are created on adEntered only). Decide: intended removal (delete this spec) or regression (restore discovery-time ad preloading)."
|
|
52079
|
-
);
|
|
52080
|
-
const [main] = createLoadOptionsList(1);
|
|
52081
|
-
trackController.load(main);
|
|
52082
|
-
const track2 = trackController.activeTrack;
|
|
52083
|
-
const ads = {
|
|
52084
|
-
trackUri: main.uri,
|
|
52085
|
-
adBreaks: [
|
|
52086
|
-
{
|
|
52087
|
-
id: "b1",
|
|
52088
|
-
startTime: 5,
|
|
52089
|
-
duration: 10,
|
|
52090
|
-
placement: "midroll",
|
|
52091
|
-
restrict: {},
|
|
52092
|
-
once: false,
|
|
52093
|
-
resumeOffset: null,
|
|
52094
|
-
playoutLimit: null,
|
|
52095
|
-
resolutionTimeOffset: null,
|
|
52096
|
-
skipControl: () => null,
|
|
52097
|
-
ads: () => Promise.resolve([
|
|
52098
|
-
{
|
|
52099
|
-
id: "a1",
|
|
52100
|
-
startTime: 5,
|
|
52101
|
-
duration: 10,
|
|
52102
|
-
uri: "https://ads/a.m3u8"
|
|
52103
|
-
}
|
|
52104
|
-
])
|
|
52105
|
-
}
|
|
52106
|
-
]
|
|
52107
|
-
};
|
|
52108
|
-
track2.ads = ads;
|
|
52109
|
-
track2.dispatch("adsChange", { previous: null, current: ads });
|
|
52110
|
-
await Promise.resolve();
|
|
52111
|
-
await Promise.resolve();
|
|
52112
|
-
await Promise.resolve();
|
|
52113
|
-
const adTrack = trackController.getCachedTrack(
|
|
52114
|
-
"https://ads/a.m3u8"
|
|
52115
|
-
);
|
|
52116
|
-
trackController.clearPrefetch();
|
|
52117
|
-
expect(adTrack.clearPrefetch).toHaveBeenCalled();
|
|
52118
|
-
});
|
|
52119
52451
|
});
|
|
52120
52452
|
describe("clearQueue", () => {
|
|
52121
52453
|
it("clears the queue without unloading the current track", async () => {
|
|
@@ -52620,6 +52952,19 @@ x`);
|
|
|
52620
52952
|
expect(adTrack).withContext("midroll ad track warmed").toBeDefined();
|
|
52621
52953
|
expect(adTrack.preload).toHaveBeenCalled();
|
|
52622
52954
|
});
|
|
52955
|
+
it("clears prefetch on a preloaded ad track", async () => {
|
|
52956
|
+
const [main] = createLoadOptionsList(1);
|
|
52957
|
+
factoryGivingBreak(main.uri, []);
|
|
52958
|
+
trackController.load(main);
|
|
52959
|
+
await flushAds();
|
|
52960
|
+
deps.adController.dispatch("adPreload", {
|
|
52961
|
+
adBreak: midrollBreak("https://ads/mid.m3u8")
|
|
52962
|
+
});
|
|
52963
|
+
await flushAds();
|
|
52964
|
+
const adTrack = created.get("https://ads/mid.m3u8");
|
|
52965
|
+
trackController.clearPrefetch();
|
|
52966
|
+
expect(adTrack.clearPrefetch).toHaveBeenCalledTimes(1);
|
|
52967
|
+
});
|
|
52623
52968
|
it("ignores adPreload when there is no parent track", () => {
|
|
52624
52969
|
expect(
|
|
52625
52970
|
() => deps.adController.dispatch("adPreload", {
|
|
@@ -52815,21 +53160,6 @@ x`);
|
|
|
52815
53160
|
objectContaining23({ startTime: 3 })
|
|
52816
53161
|
);
|
|
52817
53162
|
});
|
|
52818
|
-
it("skips the deferred resume if interrupted before the frame", async () => {
|
|
52819
|
-
pending(
|
|
52820
|
-
"REVIEW: content resume on adBreakCompleted is now synchronous (no deferred/interruptible frame), so this interruption guard no longer applies. Decide: intended or restore deferral."
|
|
52821
|
-
);
|
|
52822
|
-
const [main] = createLoadOptionsList(1);
|
|
52823
|
-
trackController.load(main);
|
|
52824
|
-
const changeSpy = createEventSpy(trackController, "trackActivated");
|
|
52825
|
-
deps.adController.dispatch("adBreakCompleted", {
|
|
52826
|
-
adBreak: adBreak("midroll"),
|
|
52827
|
-
resumePosition: 5
|
|
52828
|
-
});
|
|
52829
|
-
deps.adController.currentAd = __spreadProps(__spreadValues({}, ad), { id: "other" });
|
|
52830
|
-
await clock.tick();
|
|
52831
|
-
expect(changeSpy).not.toHaveBeenCalled();
|
|
52832
|
-
});
|
|
52833
53163
|
it("advances to the next track after a postroll ad when one exists", async () => {
|
|
52834
53164
|
var _a3;
|
|
52835
53165
|
const list = createLoadOptionsList(2);
|
|
@@ -55763,13 +56093,15 @@ x`);
|
|
|
55763
56093
|
await expectTrackCanSeekTo(player, 5);
|
|
55764
56094
|
});
|
|
55765
56095
|
it("can continue seeking", async () => {
|
|
55766
|
-
|
|
56096
|
+
let nextEnded = nextEventAsPromise(player, "ended");
|
|
55767
56097
|
await expectTrackCanSeekTo(player, 999);
|
|
55768
56098
|
await nextEnded;
|
|
55769
56099
|
await expectTrackCanSeekTo(player, 0);
|
|
55770
56100
|
await expectTrackCanSeekTo(player, 5);
|
|
55771
56101
|
await expectTrackCanSeekTo(player, 15);
|
|
55772
56102
|
await expectTrackCanSeekTo(player, 35);
|
|
56103
|
+
await player.play();
|
|
56104
|
+
nextEnded = nextEventAsPromise(player, "ended");
|
|
55773
56105
|
await expectTrackCanSeekTo(player, 999);
|
|
55774
56106
|
await nextEnded;
|
|
55775
56107
|
});
|