@amazon/vinyl 4.0.0 → 4.0.1-next.20261016220320
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +40 -3
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +41 -3
- package/dist/index.js.map +2 -2
- package/dist/test/benchmark.es5.js +5 -4
- package/dist/test/benchmark.js +11 -2
- package/dist/test/benchmark.js.map +3 -3
- package/dist/test/errata/mse-changetype-sequence.html +65 -0
- package/dist/test/errata/mse-changetype-sequence.js +179 -0
- package/dist/test/index.html +2 -2
- package/dist/test/integ.es5.js +287 -276
- package/dist/test/integ.js +629 -245
- package/dist/test/integ.js.map +4 -4
- package/dist/test/styles.css +23 -13
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts +12 -0
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
- package/dist/types/current/playback/PlaybackControllerImpl.js +42 -1
- package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.js +9 -2
- package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -2
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +12 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +12 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +12 -0
- package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +86 -0
- package/dist/unit/types/current/setup.js +6 -5
- package/dist/unit/types/current/streaming/SegmentControllerImpl.test.js +44 -1
- package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +14 -0
- package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +13 -0
- package/dist/unit/types/current/track/dash/createDashFactories.test.js +15 -5
- package/dist/unit/types/current/track/hls/createHlsFactories.test.js +36 -12
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/unit/types/current/vinyl/VinylPlayerAdBreaks.test.js +8 -5
- package/dist/vinylTestUtil/index.js +92 -60
- package/dist/vinylTestUtil/index.js.map +4 -4
- package/dist/vinylTestUtil/types/current/media/FrequencyAnalyzer.d.ts +8 -5
- package/dist/vinylTestUtil/types/current/media/FrequencyAnalyzer.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/media/FrequencyAnalyzer.js +23 -29
- package/dist/vinylTestUtil/types/current/media/unlockMediaElement.d.ts +10 -1
- package/dist/vinylTestUtil/types/current/media/unlockMediaElement.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/media/unlockMediaElement.js +34 -6
- package/dist/vinylTestUtil/types/current/player/createVinylSuite.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/player/createVinylSuite.js +6 -1
- package/dist/vinylTestUtil/types/current/player/mediaRef.d.ts +7 -0
- package/dist/vinylTestUtil/types/current/player/mediaRef.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/player/mediaRef.js +8 -1
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/current/ui/requireUserInteraction.d.ts +6 -2
- package/dist/vinylTestUtil/types/current/ui/requireUserInteraction.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/ui/requireUserInteraction.js +31 -15
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlays.d.ts +9 -2
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlays.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlays.js +10 -7
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlaysUntil.d.ts +4 -1
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlaysUntil.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/util/playback/expectTrackPlaysUntil.js +3 -2
- package/dist/vinylTestUtil/types/ts3.7/media/FrequencyAnalyzer.d.ts +8 -5
- package/dist/vinylTestUtil/types/ts3.7/media/unlockMediaElement.d.ts +10 -1
- package/dist/vinylTestUtil/types/ts3.7/player/mediaRef.d.ts +7 -0
- package/dist/vinylTestUtil/types/ts3.7/ui/requireUserInteraction.d.ts +6 -2
- package/dist/vinylTestUtil/types/ts3.7/util/playback/expectTrackPlays.d.ts +9 -2
- package/dist/vinylTestUtil/types/ts3.7/util/playback/expectTrackPlaysUntil.d.ts +4 -1
- package/dist/vinylTestUtil/types/ts4.1/media/FrequencyAnalyzer.d.ts +8 -5
- package/dist/vinylTestUtil/types/ts4.1/media/unlockMediaElement.d.ts +10 -1
- package/dist/vinylTestUtil/types/ts4.1/player/mediaRef.d.ts +7 -0
- package/dist/vinylTestUtil/types/ts4.1/ui/requireUserInteraction.d.ts +6 -2
- package/dist/vinylTestUtil/types/ts4.1/util/playback/expectTrackPlays.d.ts +9 -2
- package/dist/vinylTestUtil/types/ts4.1/util/playback/expectTrackPlaysUntil.d.ts +4 -1
- package/dist/vinylTestUtil/types/ts4.7/media/FrequencyAnalyzer.d.ts +8 -5
- package/dist/vinylTestUtil/types/ts4.7/media/unlockMediaElement.d.ts +10 -1
- package/dist/vinylTestUtil/types/ts4.7/player/mediaRef.d.ts +7 -0
- package/dist/vinylTestUtil/types/ts4.7/ui/requireUserInteraction.d.ts +6 -2
- package/dist/vinylTestUtil/types/ts4.7/util/playback/expectTrackPlays.d.ts +9 -2
- package/dist/vinylTestUtil/types/ts4.7/util/playback/expectTrackPlaysUntil.d.ts +4 -1
- package/package.json +11 -10
package/dist/test/integ.js
CHANGED
|
@@ -1135,7 +1135,7 @@
|
|
|
1135
1135
|
var uncurryThis = require_function_uncurry_this();
|
|
1136
1136
|
var hasOwn = require_has_own_property();
|
|
1137
1137
|
var toIndexedObject = require_to_indexed_object();
|
|
1138
|
-
var
|
|
1138
|
+
var indexOf2 = require_array_includes().indexOf;
|
|
1139
1139
|
var hiddenKeys = require_hidden_keys();
|
|
1140
1140
|
var push = uncurryThis([].push);
|
|
1141
1141
|
module.exports = function(object2, names) {
|
|
@@ -1145,7 +1145,7 @@
|
|
|
1145
1145
|
var key;
|
|
1146
1146
|
for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
|
|
1147
1147
|
while (names.length > i) if (hasOwn(O, key = names[i++])) {
|
|
1148
|
-
~
|
|
1148
|
+
~indexOf2(result, key) || push(result, key);
|
|
1149
1149
|
}
|
|
1150
1150
|
return result;
|
|
1151
1151
|
};
|
|
@@ -3860,10 +3860,6 @@
|
|
|
3860
3860
|
if (nextTestTimeoutOverridden) nextTestTimeoutOverridden = false;
|
|
3861
3861
|
});
|
|
3862
3862
|
}
|
|
3863
|
-
function setNextTestTimeout(timeout2) {
|
|
3864
|
-
nextTestTimeoutOverridden = true;
|
|
3865
|
-
jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout2 * 1e3;
|
|
3866
|
-
}
|
|
3867
3863
|
|
|
3868
3864
|
// ../vinyl-util/test/browserTestUtil/expect/expectIterableEquals.ts
|
|
3869
3865
|
function expectIterableEquals(arr1, arr2) {
|
|
@@ -4509,7 +4505,7 @@
|
|
|
4509
4505
|
__publicField(this, "onsourceended", null);
|
|
4510
4506
|
__publicField(this, "onsourceopen", null);
|
|
4511
4507
|
__publicField(this, "readyState", "closed");
|
|
4512
|
-
__publicField(this, "sourceBuffers");
|
|
4508
|
+
__publicField(this, "sourceBuffers", []);
|
|
4513
4509
|
__publicField(this, "addSourceBuffer", createSpy2("addSourceBuffer"));
|
|
4514
4510
|
__publicField(this, "clearLiveSeekableRange", createSpy2(
|
|
4515
4511
|
"clearLiveSeekableRange"
|
|
@@ -5598,6 +5594,9 @@
|
|
|
5598
5594
|
}
|
|
5599
5595
|
|
|
5600
5596
|
// ../vinyl-util/src/util/collection/array.ts
|
|
5597
|
+
function indexOf(arrayLike, element2) {
|
|
5598
|
+
return Array.prototype.indexOf.call(arrayLike, element2);
|
|
5599
|
+
}
|
|
5601
5600
|
function map(arrayLike, transform, thisArg) {
|
|
5602
5601
|
return Array.prototype.map.call(arrayLike, transform, thisArg);
|
|
5603
5602
|
}
|
|
@@ -14016,32 +14015,32 @@ ${this.lastInitStack}` : "";
|
|
|
14016
14015
|
}
|
|
14017
14016
|
function getRepresentationAncestry(representation) {
|
|
14018
14017
|
const adaptationSet = representation.parent;
|
|
14019
|
-
const
|
|
14020
|
-
const mpd =
|
|
14021
|
-
return [mpd,
|
|
14018
|
+
const period2 = adaptationSet.parent;
|
|
14019
|
+
const mpd = period2.parent;
|
|
14020
|
+
return [mpd, period2, adaptationSet, representation];
|
|
14022
14021
|
}
|
|
14023
14022
|
function mergeIfAnyDefined(...sources) {
|
|
14024
14023
|
if (!sources.some((source) => source)) return void 0;
|
|
14025
14024
|
return merge(...sources);
|
|
14026
14025
|
}
|
|
14027
|
-
function calculatePeriodTimeRange(
|
|
14028
|
-
return [calculatePeriodStart(
|
|
14026
|
+
function calculatePeriodTimeRange(period2) {
|
|
14027
|
+
return [calculatePeriodStart(period2), calculatePeriodEnd(period2)];
|
|
14029
14028
|
}
|
|
14030
|
-
function calculatePeriodStart(
|
|
14031
|
-
if (
|
|
14032
|
-
const mpd =
|
|
14033
|
-
const periodIndex = mpd.Period.indexOf(
|
|
14029
|
+
function calculatePeriodStart(period2) {
|
|
14030
|
+
if (period2.start != null) return period2.start;
|
|
14031
|
+
const mpd = period2.parent;
|
|
14032
|
+
const periodIndex = mpd.Period.indexOf(period2);
|
|
14034
14033
|
if (periodIndex <= 0) return 0;
|
|
14035
14034
|
const previous = mpd.Period[periodIndex - 1];
|
|
14036
14035
|
const previousStart = calculatePeriodStart(previous);
|
|
14037
14036
|
return previous.duration != null ? previousStart + previous.duration : previousStart;
|
|
14038
14037
|
}
|
|
14039
|
-
function calculatePeriodEnd(
|
|
14038
|
+
function calculatePeriodEnd(period2) {
|
|
14040
14039
|
var _a3;
|
|
14041
|
-
if (
|
|
14042
|
-
return calculatePeriodStart(
|
|
14043
|
-
const mpd =
|
|
14044
|
-
const periodIndex = mpd.Period.indexOf(
|
|
14040
|
+
if (period2.duration != null)
|
|
14041
|
+
return calculatePeriodStart(period2) + period2.duration;
|
|
14042
|
+
const mpd = period2.parent;
|
|
14043
|
+
const periodIndex = mpd.Period.indexOf(period2);
|
|
14045
14044
|
if (periodIndex < mpd.Period.length - 1)
|
|
14046
14045
|
return calculatePeriodStart(mpd.Period[periodIndex + 1]);
|
|
14047
14046
|
else return (_a3 = mpd.mediaPresentationDuration) != null ? _a3 : null;
|
|
@@ -14050,18 +14049,18 @@ ${this.lastInitStack}` : "";
|
|
|
14050
14049
|
return periodStart + (sampleTime - presentationTimeOffset) / timescale;
|
|
14051
14050
|
}
|
|
14052
14051
|
function getPeriodAtTime(manifest3, time) {
|
|
14053
|
-
const index = sortedInsertionIndex(manifest3.MPD.Period, time, (time2,
|
|
14054
|
-
return time2 - calculatePeriodStart(
|
|
14052
|
+
const index = sortedInsertionIndex(manifest3.MPD.Period, time, (time2, period3) => {
|
|
14053
|
+
return time2 - calculatePeriodStart(period3);
|
|
14055
14054
|
}) - 1;
|
|
14056
14055
|
if (index < 0) return null;
|
|
14057
|
-
const
|
|
14058
|
-
const periodEnd = calculatePeriodEnd(
|
|
14059
|
-
return periodEnd != null && time >= periodEnd ? null :
|
|
14056
|
+
const period2 = manifest3.MPD.Period[index];
|
|
14057
|
+
const periodEnd = calculatePeriodEnd(period2);
|
|
14058
|
+
return periodEnd != null && time >= periodEnd ? null : period2;
|
|
14060
14059
|
}
|
|
14061
|
-
function flattenRepresentations(
|
|
14060
|
+
function flattenRepresentations(period2) {
|
|
14062
14061
|
var _a3;
|
|
14063
14062
|
const out = [];
|
|
14064
|
-
(_a3 =
|
|
14063
|
+
(_a3 = period2.AdaptationSet) == null ? void 0 : _a3.forEach((adaptationSet) => {
|
|
14065
14064
|
var _a4;
|
|
14066
14065
|
(_a4 = adaptationSet.Representation) == null ? void 0 : _a4.forEach((representation) => {
|
|
14067
14066
|
out.push(representation);
|
|
@@ -14069,8 +14068,8 @@ ${this.lastInitStack}` : "";
|
|
|
14069
14068
|
});
|
|
14070
14069
|
return out;
|
|
14071
14070
|
}
|
|
14072
|
-
function flattenMediaRepresentations(
|
|
14073
|
-
return flattenRepresentations(
|
|
14071
|
+
function flattenMediaRepresentations(period2) {
|
|
14072
|
+
return flattenRepresentations(period2).filter((representation) => {
|
|
14074
14073
|
const { contentType: contentType2 } = getRepresentationMimeInfo(representation);
|
|
14075
14074
|
return contentType2 === "audio" || contentType2 === "video";
|
|
14076
14075
|
});
|
|
@@ -14120,9 +14119,9 @@ ${this.lastInitStack}` : "";
|
|
|
14120
14119
|
const periods = manifest3.MPD.Period;
|
|
14121
14120
|
const avails = [];
|
|
14122
14121
|
const breaks = [];
|
|
14123
|
-
for (const
|
|
14124
|
-
const periodStart = calculatePeriodStart(
|
|
14125
|
-
for (const eventStream of (_a3 =
|
|
14122
|
+
for (const period2 of periods) {
|
|
14123
|
+
const periodStart = calculatePeriodStart(period2);
|
|
14124
|
+
for (const eventStream of (_a3 = period2.EventStream) != null ? _a3 : []) {
|
|
14126
14125
|
const { schemeIdUri } = eventStream;
|
|
14127
14126
|
const isScte35 = SCTE35_SCHEMES.has(schemeIdUri);
|
|
14128
14127
|
const isInsert = schemeIdUri === DashAlternativeMpdScheme.INSERT;
|
|
@@ -14302,16 +14301,16 @@ ${this.lastInitStack}` : "";
|
|
|
14302
14301
|
var _a3, _b;
|
|
14303
14302
|
const endTime = duration == null ? Infinity : startTime + duration;
|
|
14304
14303
|
const ads = [];
|
|
14305
|
-
for (const
|
|
14306
|
-
const periodStart = calculatePeriodStart(
|
|
14304
|
+
for (const period2 of periods) {
|
|
14305
|
+
const periodStart = calculatePeriodStart(period2);
|
|
14307
14306
|
if (periodStart < startTime - SPAN_EPSILON || periodStart >= endTime - SPAN_EPSILON)
|
|
14308
14307
|
continue;
|
|
14309
14308
|
const periodEnd = Math.min(
|
|
14310
|
-
(_a3 = calculatePeriodEnd(
|
|
14309
|
+
(_a3 = calculatePeriodEnd(period2)) != null ? _a3 : endTime,
|
|
14311
14310
|
endTime
|
|
14312
14311
|
);
|
|
14313
14312
|
ads.push({
|
|
14314
|
-
id: (_b =
|
|
14313
|
+
id: (_b = period2.id) != null ? _b : `${breakId}-${ads.length}`,
|
|
14315
14314
|
startTime: periodStart,
|
|
14316
14315
|
duration: Number.isFinite(periodEnd) ? periodEnd - periodStart : null,
|
|
14317
14316
|
uri: null
|
|
@@ -14399,13 +14398,13 @@ ${this.lastInitStack}` : "";
|
|
|
14399
14398
|
}
|
|
14400
14399
|
if (mpd.type !== "list") return single;
|
|
14401
14400
|
const ads = [];
|
|
14402
|
-
for (const
|
|
14403
|
-
const imported = (_b = (_a3 =
|
|
14401
|
+
for (const period2 of mpd.Period) {
|
|
14402
|
+
const imported = (_b = (_a3 = period2.ImportedMPD) == null ? void 0 : _a3._content) == null ? void 0 : _b.trim();
|
|
14404
14403
|
if (!imported) continue;
|
|
14405
14404
|
ads.push({
|
|
14406
|
-
id: (_c =
|
|
14405
|
+
id: (_c = period2.id) != null ? _c : `${id}-${ads.length}`,
|
|
14407
14406
|
startTime,
|
|
14408
|
-
duration: (_d =
|
|
14407
|
+
duration: (_d = period2.duration) != null ? _d : null,
|
|
14409
14408
|
uri: resolveUrl(imported, documentUrl)
|
|
14410
14409
|
});
|
|
14411
14410
|
}
|
|
@@ -17433,6 +17432,8 @@ ${this.lastInitStack}` : "";
|
|
|
17433
17432
|
this.initializeMutedEvent();
|
|
17434
17433
|
this.initializeLoopedEvent();
|
|
17435
17434
|
this.initializeReadyStateChangeEvent();
|
|
17435
|
+
this.initializeSeekWaitingEvent();
|
|
17436
|
+
this.initializeSeekPlayingEvent();
|
|
17436
17437
|
}
|
|
17437
17438
|
/**
|
|
17438
17439
|
* Re-dispatches the plain DOM events without extra information.
|
|
@@ -17457,7 +17458,11 @@ ${this.lastInitStack}` : "";
|
|
|
17457
17458
|
"waiting",
|
|
17458
17459
|
"waitingForKey"
|
|
17459
17460
|
]) {
|
|
17460
|
-
this.domEvents.on(toLowerCase(key), () =>
|
|
17461
|
+
this.domEvents.on(toLowerCase(key), () => {
|
|
17462
|
+
if (key === "waiting" && this._waiting) return;
|
|
17463
|
+
if (key === "playing" && this._playing) return;
|
|
17464
|
+
this.dispatch(key, {});
|
|
17465
|
+
});
|
|
17461
17466
|
}
|
|
17462
17467
|
this.domEvents.on("progress", (e) => {
|
|
17463
17468
|
this.dispatch("progress", { loaded: e.loaded, total: e.total });
|
|
@@ -17868,6 +17873,34 @@ ${this.lastInitStack}` : "";
|
|
|
17868
17873
|
if (!this.paused && !seekAbort.aborted()) this.startStallDetection();
|
|
17869
17874
|
}
|
|
17870
17875
|
}
|
|
17876
|
+
/**
|
|
17877
|
+
* Dispatches `waiting` when a seek while playing targets an unbuffered position and the media element did not.
|
|
17878
|
+
* Safari 27 keeps its readyState while seeking, so it never fires `waiting` for the seek.
|
|
17879
|
+
* @private
|
|
17880
|
+
*/
|
|
17881
|
+
initializeSeekWaitingEvent() {
|
|
17882
|
+
const timeoutSlot = this.disposer.add(new TimeoutSlot());
|
|
17883
|
+
this.domEvents.on("seeking", () => {
|
|
17884
|
+
timeoutSlot.set(() => {
|
|
17885
|
+
const media = this.media;
|
|
17886
|
+
if (this._waiting || !media.seeking || media.paused) return;
|
|
17887
|
+
const range = this.buffered.getRangeAt(media.currentTime);
|
|
17888
|
+
if (range && range[1] > media.currentTime) return;
|
|
17889
|
+
this.dispatch("waiting", {});
|
|
17890
|
+
}, 0);
|
|
17891
|
+
});
|
|
17892
|
+
}
|
|
17893
|
+
/**
|
|
17894
|
+
* Dispatches `playing` when a seek while playing completes and the media element did not. A seek ends `playing`,
|
|
17895
|
+
* but WebKit only fires `playing` again if its readyState dropped, which it doesn't for a buffered position.
|
|
17896
|
+
* @private
|
|
17897
|
+
*/
|
|
17898
|
+
initializeSeekPlayingEvent() {
|
|
17899
|
+
this.domEvents.on("seeked", () => {
|
|
17900
|
+
if (this._playing || this.media.paused || !this.canPlay) return;
|
|
17901
|
+
this.dispatch("playing", {});
|
|
17902
|
+
});
|
|
17903
|
+
}
|
|
17871
17904
|
/**
|
|
17872
17905
|
* Dispatches a readyStateChange event when {@link readyState} changes.
|
|
17873
17906
|
* @private
|
|
@@ -18399,7 +18432,8 @@ ${this.lastInitStack}` : "";
|
|
|
18399
18432
|
return;
|
|
18400
18433
|
}
|
|
18401
18434
|
this.bufferingQuality = streamingSegment.quality;
|
|
18402
|
-
|
|
18435
|
+
const reinitialized = this.decoderId !== streamingSegment.quality.decoderId;
|
|
18436
|
+
if (reinitialized) {
|
|
18403
18437
|
this.decoderId = null;
|
|
18404
18438
|
await sourceBufferController.appendInit(
|
|
18405
18439
|
streamingSegment.initData,
|
|
@@ -18411,6 +18445,8 @@ ${this.lastInitStack}` : "";
|
|
|
18411
18445
|
await sourceBufferController.setTimestampOffset(
|
|
18412
18446
|
streamingSegment.timestampOffset
|
|
18413
18447
|
);
|
|
18448
|
+
} else if (reinitialized) {
|
|
18449
|
+
await sourceBufferController.setTimestampOffset(tail.endTime);
|
|
18414
18450
|
}
|
|
18415
18451
|
const maxAppendSize = this.getMaxAppendSize(
|
|
18416
18452
|
streamingSegment.quality.contentType
|
|
@@ -18797,7 +18833,7 @@ ${this.lastInitStack}` : "";
|
|
|
18797
18833
|
"removing source buffer from media source",
|
|
18798
18834
|
mediaSource.readyState
|
|
18799
18835
|
);
|
|
18800
|
-
if (mediaSource.readyState !== "closed") {
|
|
18836
|
+
if (mediaSource.readyState !== "closed" && indexOf(mediaSource.sourceBuffers, sourceBuffer) !== -1) {
|
|
18801
18837
|
mediaSource.removeSourceBuffer(sourceBuffer);
|
|
18802
18838
|
}
|
|
18803
18839
|
this.sourceBuffers.delete(sourceBuffer);
|
|
@@ -19816,12 +19852,12 @@ ${this.lastInitStack}` : "";
|
|
|
19816
19852
|
(qualities) => qualities,
|
|
19817
19853
|
1
|
|
19818
19854
|
);
|
|
19819
|
-
const periods = timeline.periods.map((
|
|
19820
|
-
const filtered =
|
|
19821
|
-
(q, index) => filter(q.metadata, index, mapMetadataArray(
|
|
19855
|
+
const periods = timeline.periods.map((period2) => {
|
|
19856
|
+
const filtered = period2.qualities.filter(
|
|
19857
|
+
(q, index) => filter(q.metadata, index, mapMetadataArray(period2.qualities))
|
|
19822
19858
|
);
|
|
19823
|
-
assertMediaStreamsRetained(
|
|
19824
|
-
return __spreadProps(__spreadValues({},
|
|
19859
|
+
assertMediaStreamsRetained(period2.qualities, filtered, throwError);
|
|
19860
|
+
return __spreadProps(__spreadValues({}, period2), { qualities: filtered });
|
|
19825
19861
|
});
|
|
19826
19862
|
return __spreadProps(__spreadValues({}, timeline), { periods });
|
|
19827
19863
|
}
|
|
@@ -19832,16 +19868,16 @@ ${this.lastInitStack}` : "";
|
|
|
19832
19868
|
1
|
|
19833
19869
|
);
|
|
19834
19870
|
const periods = [];
|
|
19835
|
-
for (const
|
|
19871
|
+
for (const period2 of timeline.periods) {
|
|
19836
19872
|
const filtered = [];
|
|
19837
|
-
const metadataArray = mapMetadataArray(
|
|
19838
|
-
for (let i = 0; i <
|
|
19839
|
-
if (await filter(
|
|
19840
|
-
filtered.push(
|
|
19873
|
+
const metadataArray = mapMetadataArray(period2.qualities);
|
|
19874
|
+
for (let i = 0; i < period2.qualities.length; i++) {
|
|
19875
|
+
if (await filter(period2.qualities[i].metadata, i, metadataArray)) {
|
|
19876
|
+
filtered.push(period2.qualities[i]);
|
|
19841
19877
|
}
|
|
19842
19878
|
}
|
|
19843
|
-
assertMediaStreamsRetained(
|
|
19844
|
-
periods.push(__spreadProps(__spreadValues({},
|
|
19879
|
+
assertMediaStreamsRetained(period2.qualities, filtered, throwError);
|
|
19880
|
+
periods.push(__spreadProps(__spreadValues({}, period2), { qualities: filtered }));
|
|
19845
19881
|
}
|
|
19846
19882
|
return __spreadProps(__spreadValues({}, timeline), { periods });
|
|
19847
19883
|
}
|
|
@@ -20125,12 +20161,12 @@ ${this.lastInitStack}` : "";
|
|
|
20125
20161
|
|
|
20126
20162
|
// src/streaming/MediaTimeline.ts
|
|
20127
20163
|
function getMediaPeriodAtTime(timeline, time) {
|
|
20128
|
-
const index = sortedInsertionIndex(timeline.periods, time, (time2,
|
|
20129
|
-
return time2 -
|
|
20164
|
+
const index = sortedInsertionIndex(timeline.periods, time, (time2, period3) => {
|
|
20165
|
+
return time2 - period3.startTime;
|
|
20130
20166
|
}) - 1;
|
|
20131
20167
|
if (index < 0) return null;
|
|
20132
|
-
const
|
|
20133
|
-
return time >=
|
|
20168
|
+
const period2 = timeline.periods[index];
|
|
20169
|
+
return time >= period2.endTime ? null : period2;
|
|
20134
20170
|
}
|
|
20135
20171
|
|
|
20136
20172
|
// src/streaming/SegmentDataSlot.ts
|
|
@@ -20389,9 +20425,9 @@ ${this.lastInitStack}` : "";
|
|
|
20389
20425
|
return this._cachedPeriod;
|
|
20390
20426
|
}
|
|
20391
20427
|
const timeline = await this.deps.mediaTimelineTransformed.value;
|
|
20392
|
-
const
|
|
20393
|
-
if (
|
|
20394
|
-
return
|
|
20428
|
+
const period2 = getMediaPeriodAtTime(timeline, time);
|
|
20429
|
+
if (period2) this._cachedPeriod = period2;
|
|
20430
|
+
return period2;
|
|
20395
20431
|
}
|
|
20396
20432
|
/**
|
|
20397
20433
|
* Configures this segment provider and initiates prefetching.
|
|
@@ -20648,9 +20684,9 @@ ${this.lastInitStack}` : "";
|
|
|
20648
20684
|
*/
|
|
20649
20685
|
async createSlotForTime(time) {
|
|
20650
20686
|
var _a3;
|
|
20651
|
-
const
|
|
20652
|
-
if (!
|
|
20653
|
-
const contentTypeQualities =
|
|
20687
|
+
const period2 = await this.getPeriodAtTime(time);
|
|
20688
|
+
if (!period2) return null;
|
|
20689
|
+
const contentTypeQualities = period2.qualities.filter(
|
|
20654
20690
|
(q) => q.metadata.contentType === this.contentType
|
|
20655
20691
|
);
|
|
20656
20692
|
const playableQualities = contentTypeQualities.filter(
|
|
@@ -20800,9 +20836,9 @@ ${this.lastInitStack}` : "";
|
|
|
20800
20836
|
const periods = manifest3.MPD.Period;
|
|
20801
20837
|
const mpdBase = chainBase(baseUrl, manifest3.MPD.BaseURL);
|
|
20802
20838
|
for (let p = 0; p < periods.length; p++) {
|
|
20803
|
-
const
|
|
20804
|
-
const periodBase = chainBase(mpdBase,
|
|
20805
|
-
const adaptationSets = (_a3 =
|
|
20839
|
+
const period2 = periods[p];
|
|
20840
|
+
const periodBase = chainBase(mpdBase, period2.BaseURL);
|
|
20841
|
+
const adaptationSets = (_a3 = period2.AdaptationSet) != null ? _a3 : [];
|
|
20806
20842
|
for (const adaptationSet of adaptationSets) {
|
|
20807
20843
|
if (!isTextAdaptationSet(adaptationSet)) continue;
|
|
20808
20844
|
const asBase = chainBase(periodBase, adaptationSet.BaseURL);
|
|
@@ -22328,9 +22364,9 @@ ${this.lastInitStack}` : "";
|
|
|
22328
22364
|
updateQualities() {
|
|
22329
22365
|
this.withTimeline(this.deps.mediaTimelineTransformed, (timeline) => {
|
|
22330
22366
|
const time = this.deps.playbackController.currentTime;
|
|
22331
|
-
const
|
|
22332
|
-
this._cachedPeriod =
|
|
22333
|
-
const newQualities =
|
|
22367
|
+
const period2 = getMediaPeriodAtTime(timeline, time);
|
|
22368
|
+
this._cachedPeriod = period2;
|
|
22369
|
+
const newQualities = period2 ? period2.qualities.map((q) => q.metadata) : null;
|
|
22334
22370
|
if (!equalDeep(newQualities, this._qualities)) {
|
|
22335
22371
|
const previous = this._qualities;
|
|
22336
22372
|
this._qualities = newQualities;
|
|
@@ -22356,8 +22392,8 @@ ${this.lastInitStack}` : "";
|
|
|
22356
22392
|
updateQualitiesUnfiltered() {
|
|
22357
22393
|
this.withTimeline(this.deps.mediaTimeline, (timeline) => {
|
|
22358
22394
|
const time = this.deps.playbackController.currentTime;
|
|
22359
|
-
const
|
|
22360
|
-
const newQualities =
|
|
22395
|
+
const period2 = getMediaPeriodAtTime(timeline, time);
|
|
22396
|
+
const newQualities = period2 ? period2.qualities.map((q) => q.metadata) : null;
|
|
22361
22397
|
if (!equalDeep(newQualities, this._qualitiesUnfiltered)) {
|
|
22362
22398
|
const previous = this._qualitiesUnfiltered;
|
|
22363
22399
|
this._qualitiesUnfiltered = newQualities;
|
|
@@ -23050,11 +23086,11 @@ ${this.lastInitStack}` : "";
|
|
|
23050
23086
|
// src/track/dash/buildDashMediaTimeline.ts
|
|
23051
23087
|
function buildDashMediaTimeline(deps, data2) {
|
|
23052
23088
|
const { manifest: manifest3, baseUrl } = data2;
|
|
23053
|
-
const periods = manifest3.MPD.Period.map((
|
|
23089
|
+
const periods = manifest3.MPD.Period.map((period2) => {
|
|
23054
23090
|
var _a3;
|
|
23055
|
-
const startTime = calculatePeriodStart(
|
|
23056
|
-
const endTime = (_a3 = calculatePeriodEnd(
|
|
23057
|
-
const representations = flattenMediaRepresentations(
|
|
23091
|
+
const startTime = calculatePeriodStart(period2);
|
|
23092
|
+
const endTime = (_a3 = calculatePeriodEnd(period2)) != null ? _a3 : Infinity;
|
|
23093
|
+
const representations = flattenMediaRepresentations(period2);
|
|
23058
23094
|
const qualities = representations.map(
|
|
23059
23095
|
(representation) => {
|
|
23060
23096
|
const metadata = deps.mediaQualityMetadataResolver(representation);
|
|
@@ -23113,9 +23149,9 @@ ${this.lastInitStack}` : "";
|
|
|
23113
23149
|
}
|
|
23114
23150
|
function getContentTypes(deps, manifest3) {
|
|
23115
23151
|
const contentTypes = /* @__PURE__ */ new Set();
|
|
23116
|
-
for (const
|
|
23117
|
-
if (!
|
|
23118
|
-
const mediaMetadata = flattenMediaRepresentations(
|
|
23152
|
+
for (const period2 of manifest3.MPD.Period) {
|
|
23153
|
+
if (!period2.AdaptationSet) continue;
|
|
23154
|
+
const mediaMetadata = flattenMediaRepresentations(period2).map(
|
|
23119
23155
|
deps.mediaQualityMetadataResolver
|
|
23120
23156
|
);
|
|
23121
23157
|
for (const { contentType: contentType2 } of mediaMetadata) {
|
|
@@ -23128,9 +23164,9 @@ ${this.lastInitStack}` : "";
|
|
|
23128
23164
|
// src/track/dash/manifestTransformUtils.ts
|
|
23129
23165
|
function manifestIsPlayable(manifest3) {
|
|
23130
23166
|
return manifest3.MPD.Period.every(
|
|
23131
|
-
(
|
|
23167
|
+
(period2) => {
|
|
23132
23168
|
var _a3;
|
|
23133
|
-
return (_a3 =
|
|
23169
|
+
return (_a3 = period2.AdaptationSet) == null ? void 0 : _a3.some(
|
|
23134
23170
|
(adaptationSet) => {
|
|
23135
23171
|
var _a4;
|
|
23136
23172
|
return (_a4 = adaptationSet.Representation) == null ? void 0 : _a4.length;
|
|
@@ -23141,9 +23177,9 @@ ${this.lastInitStack}` : "";
|
|
|
23141
23177
|
}
|
|
23142
23178
|
function filterDashRepresentations(filter, throwError, manifest3) {
|
|
23143
23179
|
const result = clone(manifest3);
|
|
23144
|
-
for (const
|
|
23145
|
-
if (
|
|
23146
|
-
for (const adaptationSet of
|
|
23180
|
+
for (const period2 of result.MPD.Period) {
|
|
23181
|
+
if (period2.AdaptationSet) {
|
|
23182
|
+
for (const adaptationSet of period2.AdaptationSet) {
|
|
23147
23183
|
if (adaptationSet.Representation) {
|
|
23148
23184
|
adaptationSet.Representation = adaptationSet.Representation.filter(filter);
|
|
23149
23185
|
}
|
|
@@ -23157,9 +23193,9 @@ ${this.lastInitStack}` : "";
|
|
|
23157
23193
|
}
|
|
23158
23194
|
function filterDashAdaptationSets(filter, throwError, manifest3) {
|
|
23159
23195
|
const result = clone(manifest3);
|
|
23160
|
-
for (const
|
|
23161
|
-
if (
|
|
23162
|
-
|
|
23196
|
+
for (const period2 of result.MPD.Period) {
|
|
23197
|
+
if (period2.AdaptationSet) {
|
|
23198
|
+
period2.AdaptationSet = period2.AdaptationSet.filter(filter);
|
|
23163
23199
|
}
|
|
23164
23200
|
}
|
|
23165
23201
|
if (!manifestIsPlayable(result)) {
|
|
@@ -23170,16 +23206,16 @@ ${this.lastInitStack}` : "";
|
|
|
23170
23206
|
function sortDashAdaptationSets(comparator, manifest3) {
|
|
23171
23207
|
var _a3;
|
|
23172
23208
|
const result = clone(manifest3);
|
|
23173
|
-
for (const
|
|
23174
|
-
(_a3 =
|
|
23209
|
+
for (const period2 of result.MPD.Period) {
|
|
23210
|
+
(_a3 = period2.AdaptationSet) == null ? void 0 : _a3.sort(comparator);
|
|
23175
23211
|
}
|
|
23176
23212
|
return result;
|
|
23177
23213
|
}
|
|
23178
23214
|
function sortDashRepresentations(comparator, manifest3) {
|
|
23179
23215
|
const result = clone(manifest3);
|
|
23180
|
-
for (const
|
|
23181
|
-
if (
|
|
23182
|
-
for (const adaptationSet of
|
|
23216
|
+
for (const period2 of result.MPD.Period) {
|
|
23217
|
+
if (period2.AdaptationSet) {
|
|
23218
|
+
for (const adaptationSet of period2.AdaptationSet) {
|
|
23183
23219
|
if (adaptationSet.Representation) {
|
|
23184
23220
|
adaptationSet.Representation.sort(comparator);
|
|
23185
23221
|
}
|
|
@@ -23241,13 +23277,13 @@ ${this.lastInitStack}` : "";
|
|
|
23241
23277
|
ErrorOrigin.MEDIA
|
|
23242
23278
|
);
|
|
23243
23279
|
const adaptationSet = representation.parent;
|
|
23244
|
-
const
|
|
23245
|
-
const mpd =
|
|
23246
|
-
const periodId = (_a3 =
|
|
23247
|
-
const adaptationSetId = (_b = adaptationSet.id) != null ? _b : `$${
|
|
23280
|
+
const period2 = adaptationSet.parent;
|
|
23281
|
+
const mpd = period2.parent;
|
|
23282
|
+
const periodId = (_a3 = period2.id) != null ? _a3 : `$${mpd.Period.indexOf(period2)}`;
|
|
23283
|
+
const adaptationSetId = (_b = adaptationSet.id) != null ? _b : `$${period2.AdaptationSet.indexOf(adaptationSet)}`;
|
|
23248
23284
|
const qualityId = `${periodId}_${adaptationSetId}_${representation.id}`;
|
|
23249
23285
|
let decoderId = `${periodId}_${adaptationSetId}`;
|
|
23250
|
-
const bitstreamSwitching = (_c = adaptationSet.bitstreamSwitching) != null ? _c :
|
|
23286
|
+
const bitstreamSwitching = (_c = adaptationSet.bitstreamSwitching) != null ? _c : period2.bitstreamSwitching;
|
|
23251
23287
|
if (!bitstreamSwitching) decoderId += `_${representation.id}`;
|
|
23252
23288
|
const groupId = `${periodId}_${adaptationSetId}`;
|
|
23253
23289
|
const switchingGroupIds = resolveAdaptationSetSwitchingGroupIds(
|
|
@@ -23326,10 +23362,10 @@ ${this.lastInitStack}` : "";
|
|
|
23326
23362
|
return total;
|
|
23327
23363
|
}
|
|
23328
23364
|
var getPeriodSortedBandwidths = memoize(
|
|
23329
|
-
(
|
|
23365
|
+
(period2) => {
|
|
23330
23366
|
var _a3, _b;
|
|
23331
23367
|
const byType = /* @__PURE__ */ new Map();
|
|
23332
|
-
for (const as of (_a3 =
|
|
23368
|
+
for (const as of (_a3 = period2.AdaptationSet) != null ? _a3 : []) {
|
|
23333
23369
|
for (const rep of (_b = as.Representation) != null ? _b : []) {
|
|
23334
23370
|
const contentType2 = getRepresentationMimeInfo(rep).contentType;
|
|
23335
23371
|
if (!contentType2) continue;
|
|
@@ -23348,7 +23384,7 @@ ${this.lastInitStack}` : "";
|
|
|
23348
23384
|
}
|
|
23349
23385
|
return byType;
|
|
23350
23386
|
},
|
|
23351
|
-
(
|
|
23387
|
+
(period2) => period2,
|
|
23352
23388
|
5
|
|
23353
23389
|
);
|
|
23354
23390
|
function contentProtectionToMetadata(contentProtection, deps) {
|
|
@@ -23441,13 +23477,13 @@ ${this.lastInitStack}` : "";
|
|
|
23441
23477
|
}
|
|
23442
23478
|
function hasRemoteContent(manifest3) {
|
|
23443
23479
|
var _a3, _b, _c, _d, _e, _f;
|
|
23444
|
-
for (const
|
|
23445
|
-
if (
|
|
23480
|
+
for (const period2 of manifest3.MPD.Period) {
|
|
23481
|
+
if (period2.ImportedMPD || period2.href || ((_a3 = period2.SegmentList) == null ? void 0 : _a3.href))
|
|
23446
23482
|
return true;
|
|
23447
|
-
for (const eventStream of (_b =
|
|
23483
|
+
for (const eventStream of (_b = period2.EventStream) != null ? _b : []) {
|
|
23448
23484
|
if (eventStream.href) return true;
|
|
23449
23485
|
}
|
|
23450
|
-
for (const adaptationSet of (_c =
|
|
23486
|
+
for (const adaptationSet of (_c = period2.AdaptationSet) != null ? _c : []) {
|
|
23451
23487
|
if (adaptationSet.href || ((_d = adaptationSet.SegmentList) == null ? void 0 : _d.href))
|
|
23452
23488
|
return true;
|
|
23453
23489
|
for (const representation of (_e = adaptationSet.Representation) != null ? _e : []) {
|
|
@@ -23459,10 +23495,10 @@ ${this.lastInitStack}` : "";
|
|
|
23459
23495
|
}
|
|
23460
23496
|
async function resolveLinkedPeriods(fetchText, mpd, baseUrl) {
|
|
23461
23497
|
const resolved = await Promise.all(
|
|
23462
|
-
mpd.Period.map(async (
|
|
23498
|
+
mpd.Period.map(async (period2) => {
|
|
23463
23499
|
var _a3;
|
|
23464
|
-
const imported =
|
|
23465
|
-
if (!imported) return [
|
|
23500
|
+
const imported = period2.ImportedMPD;
|
|
23501
|
+
if (!imported) return [period2];
|
|
23466
23502
|
const href = (_a3 = imported._content) == null ? void 0 : _a3.trim();
|
|
23467
23503
|
let importedMpd = null;
|
|
23468
23504
|
let importedUrl = "";
|
|
@@ -23474,15 +23510,15 @@ ${this.lastInitStack}` : "";
|
|
|
23474
23510
|
} catch (error) {
|
|
23475
23511
|
logWarn(
|
|
23476
23512
|
logTarget4,
|
|
23477
|
-
`Linked Period ${
|
|
23513
|
+
`Linked Period ${period2.id} import failed`,
|
|
23478
23514
|
error
|
|
23479
23515
|
);
|
|
23480
23516
|
}
|
|
23481
23517
|
}
|
|
23482
23518
|
if (!importedMpd || !isImportableMpd(importedMpd)) {
|
|
23483
|
-
return fallbackLinkedPeriod(
|
|
23519
|
+
return fallbackLinkedPeriod(period2);
|
|
23484
23520
|
}
|
|
23485
|
-
return [mergeImportedPeriod(mpd,
|
|
23521
|
+
return [mergeImportedPeriod(mpd, period2, importedMpd, importedUrl)];
|
|
23486
23522
|
})
|
|
23487
23523
|
);
|
|
23488
23524
|
mpd.Period = resolved.flat();
|
|
@@ -23492,18 +23528,18 @@ ${this.lastInitStack}` : "";
|
|
|
23492
23528
|
if (mpd.Period.length !== 1) return false;
|
|
23493
23529
|
return mpd.availabilityEndTime == null || mpd.availabilityEndTime.getTime() >= Date.now();
|
|
23494
23530
|
}
|
|
23495
|
-
function fallbackLinkedPeriod(
|
|
23496
|
-
const regular =
|
|
23531
|
+
function fallbackLinkedPeriod(period2) {
|
|
23532
|
+
const regular = period2;
|
|
23497
23533
|
delete regular.ImportedMPD;
|
|
23498
23534
|
if (!isValidPeriod(regular)) {
|
|
23499
|
-
logWarn(logTarget4, `removing unresolved Linked Period ${
|
|
23535
|
+
logWarn(logTarget4, `removing unresolved Linked Period ${period2.id}`);
|
|
23500
23536
|
return [];
|
|
23501
23537
|
}
|
|
23502
23538
|
return [regular];
|
|
23503
23539
|
}
|
|
23504
|
-
function isValidPeriod(
|
|
23540
|
+
function isValidPeriod(period2) {
|
|
23505
23541
|
var _a3;
|
|
23506
|
-
return !!((_a3 =
|
|
23542
|
+
return !!((_a3 = period2.AdaptationSet) == null ? void 0 : _a3.length) || period2.duration === 0;
|
|
23507
23543
|
}
|
|
23508
23544
|
function mergeImportedPeriod(mpd, linked, importedMpd, importedUrl) {
|
|
23509
23545
|
var _a3, _b, _c, _d, _e, _f, _g;
|
|
@@ -23621,12 +23657,12 @@ ${this.lastInitStack}` : "";
|
|
|
23621
23657
|
async function resolveRemoteChildren(fetchText, mpd, baseUrl, depth) {
|
|
23622
23658
|
const periods = (await Promise.all(
|
|
23623
23659
|
mpd.Period.map(
|
|
23624
|
-
(
|
|
23660
|
+
(period2) => resolveRemote(fetchText, PERIOD, period2, baseUrl, depth)
|
|
23625
23661
|
)
|
|
23626
23662
|
)).flat();
|
|
23627
23663
|
await Promise.all(
|
|
23628
|
-
periods.map(async (
|
|
23629
|
-
const p =
|
|
23664
|
+
periods.map(async (period2) => {
|
|
23665
|
+
const p = period2;
|
|
23630
23666
|
p.parent = mpd;
|
|
23631
23667
|
if (p.EventStream) {
|
|
23632
23668
|
p.EventStream = (await Promise.all(
|
|
@@ -24986,14 +25022,14 @@ ${this.lastInitStack}` : "";
|
|
|
24986
25022
|
}))
|
|
24987
25023
|
);
|
|
24988
25024
|
}
|
|
24989
|
-
const
|
|
25025
|
+
const period2 = {
|
|
24990
25026
|
startTime: 0,
|
|
24991
25027
|
endTime: Infinity,
|
|
24992
25028
|
qualities
|
|
24993
25029
|
};
|
|
24994
25030
|
let cachedDuration = null;
|
|
24995
25031
|
return {
|
|
24996
|
-
periods: [
|
|
25032
|
+
periods: [period2],
|
|
24997
25033
|
minBufferTime: DEFAULT_MIN_BUFFER_TIME,
|
|
24998
25034
|
getAdBreaks: () => discoverAdsFromManifest(data2),
|
|
24999
25035
|
async getDuration() {
|
|
@@ -26935,9 +26971,10 @@ ${this.lastInitStack}` : "";
|
|
|
26935
26971
|
};
|
|
26936
26972
|
|
|
26937
26973
|
// test/vinylTestUtil/player/mediaRef.ts
|
|
26974
|
+
var MEDIA_VOLUME = 1e-4;
|
|
26938
26975
|
var mediaRef = lazy(() => {
|
|
26939
26976
|
const media = document.createElement("video");
|
|
26940
|
-
media.
|
|
26977
|
+
media.volume = MEDIA_VOLUME;
|
|
26941
26978
|
media.playsInline = true;
|
|
26942
26979
|
media.disableRemotePlayback = true;
|
|
26943
26980
|
return media;
|
|
@@ -26950,36 +26987,6 @@ ${this.lastInitStack}` : "";
|
|
|
26950
26987
|
}
|
|
26951
26988
|
});
|
|
26952
26989
|
|
|
26953
|
-
// test/vinylTestUtil/ui/requireUserInteraction.ts
|
|
26954
|
-
async function requireUserInteraction() {
|
|
26955
|
-
const audioPrompt = document.getElementById("unlockAudioPrompt");
|
|
26956
|
-
audioPrompt.style.removeProperty("display");
|
|
26957
|
-
const body = document.body;
|
|
26958
|
-
body.focus();
|
|
26959
|
-
await new Promise((resolve) => {
|
|
26960
|
-
const done = () => {
|
|
26961
|
-
body.removeEventListener("click", done);
|
|
26962
|
-
body.removeEventListener("keypress", done);
|
|
26963
|
-
body.removeEventListener("touchend", done);
|
|
26964
|
-
return resolve(void 0);
|
|
26965
|
-
};
|
|
26966
|
-
body.addEventListener("click", done);
|
|
26967
|
-
body.addEventListener("keypress", done);
|
|
26968
|
-
body.addEventListener("touchend", done);
|
|
26969
|
-
});
|
|
26970
|
-
audioPrompt.style.display = "none";
|
|
26971
|
-
}
|
|
26972
|
-
|
|
26973
|
-
// test/vinylTestUtil/media/unlockMediaElement.ts
|
|
26974
|
-
async function unlockMediaElement() {
|
|
26975
|
-
const media = mediaRef.value;
|
|
26976
|
-
media.src = vinylTestAssets.prog.libmp3lame_60s_2ch_16bit_44100Hz_48kbps;
|
|
26977
|
-
await media.play().catch(noop);
|
|
26978
|
-
media.pause();
|
|
26979
|
-
media.removeAttribute("src");
|
|
26980
|
-
media.load();
|
|
26981
|
-
}
|
|
26982
|
-
|
|
26983
26990
|
// test/vinylTestUtil/media/FrequencyAnalyzer.ts
|
|
26984
26991
|
var TIME_ESTIMATE_TOLERANCE = 0.02;
|
|
26985
26992
|
var defaultFrequencyAnalyzerOptions = {
|
|
@@ -27078,6 +27085,7 @@ ${this.lastInitStack}` : "";
|
|
|
27078
27085
|
}
|
|
27079
27086
|
}
|
|
27080
27087
|
};
|
|
27088
|
+
var ANALYZER_VOLUME = 0.01;
|
|
27081
27089
|
var _a2;
|
|
27082
27090
|
var shouldCheckAudio = parseBoolean(
|
|
27083
27091
|
((_a2 = getSearchParams().get("checkAudio")) != null ? _a2 : "0").toLowerCase()
|
|
@@ -27088,26 +27096,76 @@ ${this.lastInitStack}` : "";
|
|
|
27088
27096
|
return (_a3 = frequencyAnalyzer == null ? void 0 : frequencyAnalyzer.assertFrequency()) != null ? _a3 : Promise.resolve();
|
|
27089
27097
|
}
|
|
27090
27098
|
function initializeFrequencyAnalyzer() {
|
|
27091
|
-
if (shouldCheckAudio)
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27099
|
+
if (!shouldCheckAudio) return;
|
|
27100
|
+
beforeAll(() => {
|
|
27101
|
+
const media = mediaRef.value;
|
|
27102
|
+
media.crossOrigin = "anonymous";
|
|
27103
|
+
media.volume = ANALYZER_VOLUME;
|
|
27104
|
+
const audioContext = getAudioContext();
|
|
27105
|
+
if (audioContext) {
|
|
27106
|
+
const source = audioContext.createMediaElementSource(media);
|
|
27107
|
+
frequencyAnalyzer = new FrequencyAnalyzer(audioContext, source);
|
|
27108
|
+
} else {
|
|
27109
|
+
console.warn("AudioContext not supported");
|
|
27110
|
+
}
|
|
27111
|
+
});
|
|
27112
|
+
}
|
|
27113
|
+
|
|
27114
|
+
// test/vinylTestUtil/ui/requireUserInteraction.ts
|
|
27115
|
+
async function requireUserInteraction(onInteraction) {
|
|
27116
|
+
var _a3;
|
|
27117
|
+
const prompt = document.getElementById("unlockAudioPrompt");
|
|
27118
|
+
prompt.style.removeProperty("display");
|
|
27119
|
+
(_a3 = prompt.querySelector("button")) == null ? void 0 : _a3.focus();
|
|
27120
|
+
await new Promise((resolve) => {
|
|
27121
|
+
let handling = false;
|
|
27122
|
+
const handler = (event) => {
|
|
27123
|
+
var _a4;
|
|
27124
|
+
if (handling) return;
|
|
27125
|
+
handling = true;
|
|
27126
|
+
const result = (_a4 = onInteraction == null ? void 0 : onInteraction()) != null ? _a4 : Promise.resolve();
|
|
27127
|
+
result.then(() => {
|
|
27128
|
+
prompt.removeEventListener("click", handler);
|
|
27129
|
+
document.removeEventListener("keydown", handler);
|
|
27130
|
+
resolve();
|
|
27131
|
+
}).catch((error) => {
|
|
27132
|
+
console.warn(
|
|
27133
|
+
`The ${event.type} (isTrusted: ${event.isTrusted}) was not accepted as a user gesture; interact again.`,
|
|
27134
|
+
error
|
|
27104
27135
|
);
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27136
|
+
}).finally(() => {
|
|
27137
|
+
handling = false;
|
|
27138
|
+
});
|
|
27139
|
+
};
|
|
27140
|
+
prompt.addEventListener("click", handler);
|
|
27141
|
+
document.addEventListener("keydown", handler);
|
|
27142
|
+
});
|
|
27143
|
+
prompt.style.display = "none";
|
|
27144
|
+
}
|
|
27145
|
+
|
|
27146
|
+
// test/vinylTestUtil/media/unlockMediaElement.ts
|
|
27147
|
+
var MAX_TIMEOUT_MS = 2147483647;
|
|
27148
|
+
async function unlockMediaElement() {
|
|
27149
|
+
var _a3;
|
|
27150
|
+
const media = mediaRef.value;
|
|
27151
|
+
media.src = vinylTestAssets.prog.libmp3lame_60s_2ch_16bit_44100Hz_48kbps;
|
|
27152
|
+
const played = media.play();
|
|
27153
|
+
const resumed = (_a3 = getAudioContext()) == null ? void 0 : _a3.resume().catch(noop);
|
|
27154
|
+
try {
|
|
27155
|
+
await played;
|
|
27156
|
+
} finally {
|
|
27157
|
+
media.pause();
|
|
27158
|
+
media.removeAttribute("src");
|
|
27159
|
+
media.load();
|
|
27110
27160
|
}
|
|
27161
|
+
await resumed;
|
|
27162
|
+
}
|
|
27163
|
+
function initializeMediaUnlock() {
|
|
27164
|
+
if (typeof document === "undefined") return;
|
|
27165
|
+
beforeAll(async () => {
|
|
27166
|
+
await requireUserInteraction(unlockMediaElement);
|
|
27167
|
+
console.info("Media element unlocked");
|
|
27168
|
+
}, MAX_TIMEOUT_MS);
|
|
27111
27169
|
}
|
|
27112
27170
|
|
|
27113
27171
|
// test/vinylTestUtil/mediaSource/ControlledMediaSource.ts
|
|
@@ -27377,6 +27435,8 @@ ${this.lastInitStack}` : "";
|
|
|
27377
27435
|
* failedExpectations, save this from `specDone`.
|
|
27378
27436
|
*/
|
|
27379
27437
|
__publicField(this, "failedResult", null);
|
|
27438
|
+
__publicField(this, "failures", []);
|
|
27439
|
+
__publicField(this, "statusCounts", {});
|
|
27380
27440
|
__publicField(this, "totalSpecs", 0);
|
|
27381
27441
|
__publicField(this, "totalCompleted", 0);
|
|
27382
27442
|
/**
|
|
@@ -27407,13 +27467,29 @@ ${this.lastInitStack}` : "";
|
|
|
27407
27467
|
this.maybeReportProgress();
|
|
27408
27468
|
}
|
|
27409
27469
|
specDone(result) {
|
|
27410
|
-
|
|
27411
|
-
|
|
27470
|
+
var _a3, _b;
|
|
27471
|
+
if (result.status === "failed") {
|
|
27472
|
+
(_a3 = this.failedResult) != null ? _a3 : this.failedResult = result;
|
|
27473
|
+
this.addFailure(result.fullName, result.failedExpectations);
|
|
27474
|
+
}
|
|
27475
|
+
this.statusCounts[result.status] = ((_b = this.statusCounts[result.status]) != null ? _b : 0) + 1;
|
|
27412
27476
|
this.totalCompleted++;
|
|
27413
27477
|
this.maybeReportProgress();
|
|
27414
27478
|
}
|
|
27479
|
+
suiteDone(result) {
|
|
27480
|
+
if (result.failedExpectations.length)
|
|
27481
|
+
this.addFailure(result.fullName, result.failedExpectations);
|
|
27482
|
+
}
|
|
27483
|
+
addFailure(fullName, failedExpectations) {
|
|
27484
|
+
this.failures.push({
|
|
27485
|
+
fullName,
|
|
27486
|
+
messages: failedExpectations.map((e) => e.message)
|
|
27487
|
+
});
|
|
27488
|
+
}
|
|
27415
27489
|
jasmineDone(runDetails) {
|
|
27416
27490
|
var _a3;
|
|
27491
|
+
if (runDetails.failedExpectations.length)
|
|
27492
|
+
this.addFailure("top level", runDetails.failedExpectations);
|
|
27417
27493
|
this.maybeReportProgress(true);
|
|
27418
27494
|
this.consoleInterceptor.dispose();
|
|
27419
27495
|
const reason = this.failedResult ? `${this.failedResult.fullName}:
|
|
@@ -27423,7 +27499,10 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27423
27499
|
overallStatus: runDetails.overallStatus === "incomplete" ? "passed" : runDetails.overallStatus,
|
|
27424
27500
|
totalCompleted: this.totalCompleted,
|
|
27425
27501
|
totalSpecs: this.totalSpecs,
|
|
27426
|
-
reason
|
|
27502
|
+
reason,
|
|
27503
|
+
statusCounts: this.statusCounts,
|
|
27504
|
+
failures: this.failures,
|
|
27505
|
+
seed: String(runDetails.order.seed)
|
|
27427
27506
|
};
|
|
27428
27507
|
this.onDone(body).catch((_) => {
|
|
27429
27508
|
this.onDone(body).catch((e) => {
|
|
@@ -27583,6 +27662,12 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27583
27662
|
|
|
27584
27663
|
// ../vinyl-util/test/testUtil/util/event/createEventSpy.ts
|
|
27585
27664
|
var createSpy4 = jasmine.createSpy;
|
|
27665
|
+
var pendingTimeouts = /* @__PURE__ */ new Set();
|
|
27666
|
+
if (typeof afterEach === "function")
|
|
27667
|
+
afterEach(() => {
|
|
27668
|
+
for (const abort of pendingTimeouts) abort.abort();
|
|
27669
|
+
pendingTimeouts.clear();
|
|
27670
|
+
});
|
|
27586
27671
|
function createEventSpy(host, type) {
|
|
27587
27672
|
const spy = createSpy4(String(type));
|
|
27588
27673
|
let nextCall = new Deferred();
|
|
@@ -27592,12 +27677,29 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27592
27677
|
});
|
|
27593
27678
|
const unsub = host.on(type, spy);
|
|
27594
27679
|
return Object.assign(spy, {
|
|
27595
|
-
next(
|
|
27596
|
-
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27680
|
+
next(time = 5, timeoutMessage = `event '{type}' has not been dispatched after {timeout}s.`) {
|
|
27681
|
+
const call = nextCall;
|
|
27682
|
+
const abort = new Abort();
|
|
27683
|
+
pendingTimeouts.add(abort);
|
|
27684
|
+
const settle = () => {
|
|
27685
|
+
abort.abort();
|
|
27686
|
+
pendingTimeouts.delete(abort);
|
|
27687
|
+
};
|
|
27688
|
+
return Promise.race([
|
|
27689
|
+
call,
|
|
27690
|
+
timeout(time, {
|
|
27691
|
+
abort,
|
|
27692
|
+
message: substitute(timeoutMessage, {
|
|
27693
|
+
type,
|
|
27694
|
+
timeout: time
|
|
27695
|
+
})
|
|
27600
27696
|
})
|
|
27697
|
+
]).then(() => {
|
|
27698
|
+
settle();
|
|
27699
|
+
return call;
|
|
27700
|
+
}).catch((error) => {
|
|
27701
|
+
settle();
|
|
27702
|
+
throw error;
|
|
27601
27703
|
});
|
|
27602
27704
|
},
|
|
27603
27705
|
dispose: unsub
|
|
@@ -28408,6 +28510,7 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28408
28510
|
this.visibilityChangeHandler
|
|
28409
28511
|
);
|
|
28410
28512
|
this._player = this.playerFactory();
|
|
28513
|
+
this._player.volume = shouldCheckAudio ? ANALYZER_VOLUME : MEDIA_VOLUME;
|
|
28411
28514
|
add(
|
|
28412
28515
|
this._player.on("error", (e) => {
|
|
28413
28516
|
logError(this, "player emitted error event", toJson(e));
|
|
@@ -28558,13 +28661,13 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28558
28661
|
var sleepInterval = 1;
|
|
28559
28662
|
var affordanceBefore = 1;
|
|
28560
28663
|
var affordanceAfter = 3;
|
|
28561
|
-
async function expectTrackPlaysUntil(player, endTime, timeout2 = 20) {
|
|
28664
|
+
async function expectTrackPlaysUntil(player, endTime, timeout2 = 20, { timeoutScale = 1 } = {}) {
|
|
28562
28665
|
await onPlaying(player);
|
|
28563
28666
|
await onTimeUpdate(player);
|
|
28564
28667
|
const startedBeforeEnd = player.currentTime < endTime;
|
|
28565
28668
|
await assertFrequency();
|
|
28566
28669
|
let elapsed = 0;
|
|
28567
|
-
const maxTime = endTime - player.currentTime + timeout2;
|
|
28670
|
+
const maxTime = (endTime - player.currentTime + timeout2) * timeoutScale;
|
|
28568
28671
|
while (!player.ended && player.currentTime < endTime && elapsed < maxTime) {
|
|
28569
28672
|
await sleep(sleepInterval);
|
|
28570
28673
|
elapsed += sleepInterval;
|
|
@@ -28577,7 +28680,7 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28577
28680
|
|
|
28578
28681
|
// test/vinylTestUtil/util/playback/expectTrackPlays.ts
|
|
28579
28682
|
var PLAYBACK_DURATION = 6;
|
|
28580
|
-
async function expectTrackPlays(player) {
|
|
28683
|
+
async function expectTrackPlays(player, { timeoutScale = 1 } = {}) {
|
|
28581
28684
|
const { dispose, add } = createDisposer();
|
|
28582
28685
|
const ended = add(createEventSpy(player, "ended"));
|
|
28583
28686
|
const timeUpdate = add(createEventSpy(player, "timeUpdate"));
|
|
@@ -28588,12 +28691,14 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28588
28691
|
if (player.duration > PLAYBACK_DURATION) {
|
|
28589
28692
|
await expectTrackPlaysUntil(
|
|
28590
28693
|
player,
|
|
28591
|
-
player.currentTime + PLAYBACK_DURATION / 2
|
|
28694
|
+
player.currentTime + PLAYBACK_DURATION / 2,
|
|
28695
|
+
void 0,
|
|
28696
|
+
{ timeoutScale }
|
|
28592
28697
|
);
|
|
28593
28698
|
const time = player.duration - PLAYBACK_DURATION / 2;
|
|
28594
28699
|
await player.seekTo(time);
|
|
28595
28700
|
}
|
|
28596
|
-
await ended.next(PLAYBACK_DURATION + 10);
|
|
28701
|
+
await ended.next((PLAYBACK_DURATION + 10) * timeoutScale);
|
|
28597
28702
|
expect(player.currentTime).toBeCloseToWithin(duration, 3);
|
|
28598
28703
|
expect(player.ended).withContext("ended").toBeTrue();
|
|
28599
28704
|
expect(timeUpdate.calls.count()).toBeGreaterThanOrEqual(
|
|
@@ -28601,10 +28706,10 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28601
28706
|
);
|
|
28602
28707
|
dispose();
|
|
28603
28708
|
}
|
|
28604
|
-
async function expectPlaylistPlays(player, playlist) {
|
|
28709
|
+
async function expectPlaylistPlays(player, playlist, { timeoutScale = 1 } = {}) {
|
|
28605
28710
|
var _a3;
|
|
28606
28711
|
const { dispose, add } = createDisposer();
|
|
28607
|
-
const trackTimeout = PLAYBACK_DURATION + 60;
|
|
28712
|
+
const trackTimeout = (PLAYBACK_DURATION + 60) * timeoutScale;
|
|
28608
28713
|
const queueEnded = add(createEventSpy(player, "queueEnded"));
|
|
28609
28714
|
const queueChange = add(createEventSpy(player, "queueChange"));
|
|
28610
28715
|
const trackChange = add(createEventSpy(player, "trackActivated"));
|
|
@@ -28619,8 +28724,10 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
28619
28724
|
const isLastTrack = i === playlist.length - 1;
|
|
28620
28725
|
expect((_a3 = player.activeTrack) == null ? void 0 : _a3.uri).withContext("activeTrack uri").toBe(playlist[i].uri);
|
|
28621
28726
|
const nextTrack = isLastTrack ? queueEnded.next(trackTimeout) : trackChange.next(trackTimeout);
|
|
28622
|
-
await
|
|
28623
|
-
|
|
28727
|
+
await Promise.all([
|
|
28728
|
+
expectTrackPlays(player, { timeoutScale }),
|
|
28729
|
+
nextTrack
|
|
28730
|
+
]);
|
|
28624
28731
|
assertQueueChangeCount(isLastTrack ? 0 : 1);
|
|
28625
28732
|
}
|
|
28626
28733
|
dispose();
|
|
@@ -38970,6 +39077,92 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
38970
39077
|
expect(waitedSpy).not.toHaveBeenCalled();
|
|
38971
39078
|
});
|
|
38972
39079
|
});
|
|
39080
|
+
describe("when a seek while playing targets an unbuffered position", () => {
|
|
39081
|
+
let waitingSpy;
|
|
39082
|
+
beforeEach(() => {
|
|
39083
|
+
waitingSpy = createSpy12("waiting");
|
|
39084
|
+
controller.on("waiting", waitingSpy);
|
|
39085
|
+
media.buffered = new MockTimeRanges([[0, 20]]);
|
|
39086
|
+
media.currentTime = 22;
|
|
39087
|
+
media.seeking = true;
|
|
39088
|
+
});
|
|
39089
|
+
it("emits waiting if the media element does not", async () => {
|
|
39090
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39091
|
+
expect(waitingSpy).not.toHaveBeenCalled();
|
|
39092
|
+
await clock.tick();
|
|
39093
|
+
expect(waitingSpy).toHaveBeenCalledTimes(1);
|
|
39094
|
+
expect(controller.waiting).toBeTrue();
|
|
39095
|
+
media.dispatchEvent(mockEvent("waiting"));
|
|
39096
|
+
expect(waitingSpy).toHaveBeenCalledTimes(1);
|
|
39097
|
+
media.seeking = false;
|
|
39098
|
+
media.dispatchEvent(mockEvent("playing"));
|
|
39099
|
+
expect(controller.waiting).toBeFalse();
|
|
39100
|
+
});
|
|
39101
|
+
it("emits waiting once if the media element does", async () => {
|
|
39102
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39103
|
+
media.dispatchEvent(mockEvent("waiting"));
|
|
39104
|
+
await clock.tick();
|
|
39105
|
+
expect(waitingSpy).toHaveBeenCalledTimes(1);
|
|
39106
|
+
});
|
|
39107
|
+
it("does not emit waiting when paused", async () => {
|
|
39108
|
+
media.paused = true;
|
|
39109
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39110
|
+
await clock.tick();
|
|
39111
|
+
expect(waitingSpy).not.toHaveBeenCalled();
|
|
39112
|
+
});
|
|
39113
|
+
it("does not emit waiting when the seek completes first", async () => {
|
|
39114
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39115
|
+
media.seeking = false;
|
|
39116
|
+
media.dispatchEvent(mockEvent("seeked"));
|
|
39117
|
+
await clock.tick();
|
|
39118
|
+
expect(waitingSpy).not.toHaveBeenCalled();
|
|
39119
|
+
});
|
|
39120
|
+
});
|
|
39121
|
+
describe("when a seek while playing completes", () => {
|
|
39122
|
+
let playingSpy;
|
|
39123
|
+
beforeEach(() => {
|
|
39124
|
+
media.readyState = 4 /* HAVE_ENOUGH_DATA */;
|
|
39125
|
+
media.dispatchEvent(mockEvent("playing"));
|
|
39126
|
+
playingSpy = createSpy12("playing");
|
|
39127
|
+
controller.on("playing", playingSpy);
|
|
39128
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39129
|
+
expect(controller.playing).toBeFalse();
|
|
39130
|
+
});
|
|
39131
|
+
it("emits playing if the media element does not", () => {
|
|
39132
|
+
media.dispatchEvent(mockEvent("seeked"));
|
|
39133
|
+
expect(playingSpy).toHaveBeenCalledTimes(1);
|
|
39134
|
+
expect(controller.playing).toBeTrue();
|
|
39135
|
+
media.dispatchEvent(mockEvent("playing"));
|
|
39136
|
+
expect(playingSpy).toHaveBeenCalledTimes(1);
|
|
39137
|
+
});
|
|
39138
|
+
it("emits playing once if the media element does", () => {
|
|
39139
|
+
media.dispatchEvent(mockEvent("playing"));
|
|
39140
|
+
media.dispatchEvent(mockEvent("seeked"));
|
|
39141
|
+
expect(playingSpy).toHaveBeenCalledTimes(1);
|
|
39142
|
+
});
|
|
39143
|
+
it("does not emit playing when paused", () => {
|
|
39144
|
+
media.paused = true;
|
|
39145
|
+
media.dispatchEvent(mockEvent("seeked"));
|
|
39146
|
+
expect(playingSpy).not.toHaveBeenCalled();
|
|
39147
|
+
});
|
|
39148
|
+
it("does not emit playing without future data", () => {
|
|
39149
|
+
media.readyState = 2 /* HAVE_CURRENT_DATA */;
|
|
39150
|
+
media.dispatchEvent(mockEvent("seeked"));
|
|
39151
|
+
expect(playingSpy).not.toHaveBeenCalled();
|
|
39152
|
+
});
|
|
39153
|
+
});
|
|
39154
|
+
describe("when a seek while playing targets a buffered position", () => {
|
|
39155
|
+
it("does not emit waiting", async () => {
|
|
39156
|
+
const waitingSpy = createSpy12("waiting");
|
|
39157
|
+
controller.on("waiting", waitingSpy);
|
|
39158
|
+
media.buffered = new MockTimeRanges([[0, 30]]);
|
|
39159
|
+
media.currentTime = 22;
|
|
39160
|
+
media.seeking = true;
|
|
39161
|
+
media.dispatchEvent(mockEvent("seeking"));
|
|
39162
|
+
await clock.tick();
|
|
39163
|
+
expect(waitingSpy).not.toHaveBeenCalled();
|
|
39164
|
+
});
|
|
39165
|
+
});
|
|
38973
39166
|
});
|
|
38974
39167
|
describe("pause", () => {
|
|
38975
39168
|
it("invokes pause on the element", () => {
|
|
@@ -39176,12 +39369,13 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
39176
39369
|
addCustomMatchers();
|
|
39177
39370
|
setGlobalRefDebug(true);
|
|
39178
39371
|
jasmine.getEnv().configure({
|
|
39179
|
-
stopOnSpecFailure:
|
|
39372
|
+
stopOnSpecFailure: getSearchParams().get("stopOnSpecFailure") !== "false",
|
|
39180
39373
|
stopSpecOnExpectationFailure: true,
|
|
39181
39374
|
failSpecWithNoExpectations: true
|
|
39182
39375
|
});
|
|
39183
39376
|
jasmine.getEnv().addReporter(new ConsoleReporter());
|
|
39184
39377
|
RestApiReporter.installFromSearchParam();
|
|
39378
|
+
initializeMediaUnlock();
|
|
39185
39379
|
initializeFrequencyAnalyzer();
|
|
39186
39380
|
afterEach(async () => {
|
|
39187
39381
|
await flushPromises();
|
|
@@ -40410,6 +40604,22 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
40410
40604
|
"opus"
|
|
40411
40605
|
);
|
|
40412
40606
|
});
|
|
40607
|
+
it("continues after the buffered segment once the new initialization segment is appended", async () => {
|
|
40608
|
+
await open();
|
|
40609
|
+
sourceBufferController.setTimestampOffset.calls.reset();
|
|
40610
|
+
segmentController.getSegment.and.callFake((time) => {
|
|
40611
|
+
const mockSegment = createMockSegment(time);
|
|
40612
|
+
if (mockSegment.startTime >= 10) {
|
|
40613
|
+
mockSegment.quality.decoderId = "next period";
|
|
40614
|
+
mockSegment.timestampOffset = mockSegment.startTime - 4;
|
|
40615
|
+
}
|
|
40616
|
+
return Promise.resolve(mockSegment);
|
|
40617
|
+
});
|
|
40618
|
+
await setTime(9);
|
|
40619
|
+
expect(
|
|
40620
|
+
sourceBufferController.setTimestampOffset
|
|
40621
|
+
).toHaveBeenCalledOnceWith(10);
|
|
40622
|
+
});
|
|
40413
40623
|
});
|
|
40414
40624
|
describe("when segment controller returns null", () => {
|
|
40415
40625
|
beforeEach(() => {
|
|
@@ -41199,6 +41409,11 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
41199
41409
|
).toThrowError(MediaSourceError, "error creating source buffer");
|
|
41200
41410
|
});
|
|
41201
41411
|
describe("SourceBufferRef disposal", () => {
|
|
41412
|
+
beforeEach(() => {
|
|
41413
|
+
mockMediaSource.sourceBuffers = [
|
|
41414
|
+
mockSourceBuffer
|
|
41415
|
+
];
|
|
41416
|
+
});
|
|
41202
41417
|
it("removes source buffer from media source", () => {
|
|
41203
41418
|
mockMediaSource.readyState = "open";
|
|
41204
41419
|
const ref = controller.createSourceBuffer("audio", "audio/mp4");
|
|
@@ -41216,6 +41431,15 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
41216
41431
|
mockMediaSource.removeSourceBuffer
|
|
41217
41432
|
).not.toHaveBeenCalled();
|
|
41218
41433
|
});
|
|
41434
|
+
it("does not remove a source buffer the media source already removed", () => {
|
|
41435
|
+
mockMediaSource.readyState = "open";
|
|
41436
|
+
const ref = controller.createSourceBuffer("audio", "audio/mp4");
|
|
41437
|
+
mockMediaSource.sourceBuffers = [];
|
|
41438
|
+
ref.dispose();
|
|
41439
|
+
expect(
|
|
41440
|
+
mockMediaSource.removeSourceBuffer
|
|
41441
|
+
).not.toHaveBeenCalled();
|
|
41442
|
+
});
|
|
41219
41443
|
});
|
|
41220
41444
|
});
|
|
41221
41445
|
describe("endOfStream", () => {
|
|
@@ -44783,6 +45007,51 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
44783
45007
|
});
|
|
44784
45008
|
expect(await segmentController.getSegment(5)).toBeNull();
|
|
44785
45009
|
});
|
|
45010
|
+
describe("when a codec has been denylisted", () => {
|
|
45011
|
+
const OPUS = 'audio/mp4; codecs="opus"';
|
|
45012
|
+
const AAC = 'audio/mp4; codecs="mp4a.40.2"';
|
|
45013
|
+
let selectQuality;
|
|
45014
|
+
beforeEach(() => {
|
|
45015
|
+
timelineData.value = Promise.resolve({
|
|
45016
|
+
periods: [
|
|
45017
|
+
{
|
|
45018
|
+
startTime: 0,
|
|
45019
|
+
endTime: 100,
|
|
45020
|
+
qualities: [OPUS, AAC].map((mimeType, i) => ({
|
|
45021
|
+
metadata: __spreadProps(__spreadValues({}, createEmptyMediaQualityMetadata()), {
|
|
45022
|
+
contentType: "audio",
|
|
45023
|
+
mimeType,
|
|
45024
|
+
decoderId: String(i)
|
|
45025
|
+
}),
|
|
45026
|
+
getSegment: (time) => segmentProvider.getSegment(time)
|
|
45027
|
+
}))
|
|
45028
|
+
}
|
|
45029
|
+
],
|
|
45030
|
+
minBufferTime: 10,
|
|
45031
|
+
getAdBreaks: () => Promise.resolve([]),
|
|
45032
|
+
getDuration: () => Promise.resolve(100)
|
|
45033
|
+
});
|
|
45034
|
+
selectQuality = spyOn(
|
|
45035
|
+
mockDeps.qualitySelector,
|
|
45036
|
+
"selectQuality"
|
|
45037
|
+
).and.returnValue(0);
|
|
45038
|
+
});
|
|
45039
|
+
afterEach(() => clearCodecDenylist());
|
|
45040
|
+
function selectedFrom() {
|
|
45041
|
+
return selectQuality.calls.mostRecent().args[0].map((metadata) => metadata.mimeType);
|
|
45042
|
+
}
|
|
45043
|
+
it("selects only from qualities whose codecs are not denylisted", async () => {
|
|
45044
|
+
denylistCodecsFromMimeType(OPUS);
|
|
45045
|
+
await segmentController.getSegment(5);
|
|
45046
|
+
expect(selectedFrom()).toEqual([AAC]);
|
|
45047
|
+
});
|
|
45048
|
+
it("selects from every quality if all of their codecs are denylisted", async () => {
|
|
45049
|
+
denylistCodecsFromMimeType(OPUS);
|
|
45050
|
+
denylistCodecsFromMimeType(AAC);
|
|
45051
|
+
await segmentController.getSegment(5);
|
|
45052
|
+
expect(selectedFrom()).toEqual([OPUS, AAC]);
|
|
45053
|
+
});
|
|
45054
|
+
});
|
|
44786
45055
|
it("returns null when quality getSegment returns null within period", async () => {
|
|
44787
45056
|
await fillPrefetch();
|
|
44788
45057
|
segmentController.clear();
|
|
@@ -49195,7 +49464,8 @@ x`);
|
|
|
49195
49464
|
type: "dash",
|
|
49196
49465
|
manifestProvider
|
|
49197
49466
|
});
|
|
49198
|
-
const
|
|
49467
|
+
const container = createContainer(factories);
|
|
49468
|
+
const deps = container.dependencies;
|
|
49199
49469
|
expect(deps).toEqual(
|
|
49200
49470
|
objectContaining16({
|
|
49201
49471
|
baseUrlSelector: pickFirstBaseUrlSelector,
|
|
@@ -49210,6 +49480,7 @@ x`);
|
|
|
49210
49480
|
qualitySelector: any22(QualitySelectorImpl)
|
|
49211
49481
|
})
|
|
49212
49482
|
);
|
|
49483
|
+
container.dispose();
|
|
49213
49484
|
});
|
|
49214
49485
|
it("wires per-track option observables from the player options", () => {
|
|
49215
49486
|
const factoryCreator = createDashFactories(null);
|
|
@@ -49218,11 +49489,13 @@ x`);
|
|
|
49218
49489
|
type: "dash",
|
|
49219
49490
|
manifestProvider
|
|
49220
49491
|
});
|
|
49221
|
-
const
|
|
49492
|
+
const container = createContainer(factories);
|
|
49493
|
+
const deps = container.dependencies;
|
|
49222
49494
|
const options2 = dashFactoryDeps.options.value;
|
|
49223
49495
|
expect(deps.audio.value).toBe(options2.audio);
|
|
49224
49496
|
expect(deps.allowedContentTypes.value).toBe(options2.allowedContentTypes);
|
|
49225
49497
|
expect(deps.abr.value).toBe(options2.abr);
|
|
49498
|
+
container.dispose();
|
|
49226
49499
|
});
|
|
49227
49500
|
it("provides streaming options to createContentStreamFactories", () => {
|
|
49228
49501
|
const factoryCreator = createDashFactories({
|
|
@@ -49237,8 +49510,10 @@ x`);
|
|
|
49237
49510
|
type: "dash",
|
|
49238
49511
|
manifestProvider
|
|
49239
49512
|
});
|
|
49240
|
-
const
|
|
49513
|
+
const container = createContainer(factories);
|
|
49514
|
+
const deps = container.dependencies;
|
|
49241
49515
|
expect(deps.contentStreamFactory("audio")).toEqual(any22(Object));
|
|
49516
|
+
container.dispose();
|
|
49242
49517
|
});
|
|
49243
49518
|
it("creates a sidecar text track controller and populates from manifest", async () => {
|
|
49244
49519
|
const factoryCreator = createDashFactories(null);
|
|
@@ -49267,12 +49542,14 @@ x`);
|
|
|
49267
49542
|
type: "dash",
|
|
49268
49543
|
manifestProvider: provider
|
|
49269
49544
|
});
|
|
49270
|
-
const
|
|
49545
|
+
const container = createContainer(factories);
|
|
49546
|
+
const deps = container.dependencies;
|
|
49271
49547
|
const ttc = deps.textTrackController;
|
|
49272
49548
|
await deps.manifestTransformed.value;
|
|
49273
49549
|
await new Promise((r) => setTimeout(r, 0));
|
|
49274
49550
|
expect(ttc).toBeDefined();
|
|
49275
49551
|
expect(ttc.textTracks.length).toBeGreaterThan(0);
|
|
49552
|
+
container.dispose();
|
|
49276
49553
|
});
|
|
49277
49554
|
it("text track controller swallows manifest fetch errors", async () => {
|
|
49278
49555
|
const factoryCreator = createDashFactories(null);
|
|
@@ -49284,11 +49561,13 @@ x`);
|
|
|
49284
49561
|
type: "dash",
|
|
49285
49562
|
manifestProvider: provider
|
|
49286
49563
|
});
|
|
49287
|
-
const
|
|
49564
|
+
const container = createContainer(factories);
|
|
49565
|
+
const deps = container.dependencies;
|
|
49288
49566
|
const controller = deps.textTrackController;
|
|
49289
49567
|
await deps.manifestTransformed.value.catch(() => void 0);
|
|
49290
49568
|
await new Promise((r) => setTimeout(r, 0));
|
|
49291
49569
|
expect(controller.textTracks).toEqual([]);
|
|
49570
|
+
container.dispose();
|
|
49292
49571
|
});
|
|
49293
49572
|
});
|
|
49294
49573
|
|
|
@@ -49364,9 +49643,9 @@ x`);
|
|
|
49364
49643
|
it("sorts adaptation sets by descending selectionPriority", async () => {
|
|
49365
49644
|
const result = await transform(clone(mockManifest));
|
|
49366
49645
|
const selectionPriorities = result.manifest.MPD.Period.map(
|
|
49367
|
-
(
|
|
49646
|
+
(period2) => {
|
|
49368
49647
|
var _a3;
|
|
49369
|
-
return ((_a3 =
|
|
49648
|
+
return ((_a3 = period2.AdaptationSet) != null ? _a3 : []).map((as) => as.selectionPriority);
|
|
49370
49649
|
}
|
|
49371
49650
|
);
|
|
49372
49651
|
expect(selectionPriorities).toEqual([[3, 2, 1]]);
|
|
@@ -49374,9 +49653,9 @@ x`);
|
|
|
49374
49653
|
it("sorts representations by ascending qualityRanking", async () => {
|
|
49375
49654
|
const result = await transform(clone(mockManifest));
|
|
49376
49655
|
const qualityRanks = result.manifest.MPD.Period.map(
|
|
49377
|
-
(
|
|
49656
|
+
(period2) => {
|
|
49378
49657
|
var _a3;
|
|
49379
|
-
return ((_a3 =
|
|
49658
|
+
return ((_a3 = period2.AdaptationSet) != null ? _a3 : []).map(
|
|
49380
49659
|
(as) => {
|
|
49381
49660
|
var _a4;
|
|
49382
49661
|
return ((_a4 = as.Representation) != null ? _a4 : []).map((r) => r.qualityRanking);
|
|
@@ -50410,10 +50689,10 @@ x`);
|
|
|
50410
50689
|
expect(mockRequester.request).not.toHaveBeenCalled();
|
|
50411
50690
|
});
|
|
50412
50691
|
describe("Linked Periods", () => {
|
|
50413
|
-
function imported(
|
|
50692
|
+
function imported(period2, attributes = "") {
|
|
50414
50693
|
return mpd(
|
|
50415
50694
|
`<BaseURL>media/</BaseURL>
|
|
50416
|
-
${
|
|
50695
|
+
${period2}`,
|
|
50417
50696
|
attributes
|
|
50418
50697
|
);
|
|
50419
50698
|
}
|
|
@@ -50607,18 +50886,18 @@ x`);
|
|
|
50607
50886
|
</AdaptationSet>
|
|
50608
50887
|
</Period>`)
|
|
50609
50888
|
);
|
|
50610
|
-
const [
|
|
50611
|
-
expect((_b = (_a3 =
|
|
50612
|
-
expect((_c =
|
|
50889
|
+
const [period2] = manifest3.MPD.Period;
|
|
50890
|
+
expect((_b = (_a3 = period2.SegmentList) == null ? void 0 : _a3.SegmentURL) == null ? void 0 : _b[0].media).toBe("s1.m4s");
|
|
50891
|
+
expect((_c = period2.EventStream) == null ? void 0 : _c.map((e) => e.schemeIdUri)).toEqual([
|
|
50613
50892
|
"urn:remote"
|
|
50614
50893
|
]);
|
|
50615
|
-
expect((_d =
|
|
50616
|
-
const video =
|
|
50894
|
+
expect((_d = period2.AdaptationSet) == null ? void 0 : _d.map((a) => a.id)).toEqual([1, 1, 9]);
|
|
50895
|
+
const video = period2.AdaptationSet[2];
|
|
50617
50896
|
expect((_e = video.SegmentList) == null ? void 0 : _e.duration).toBe(2);
|
|
50618
50897
|
expect((_g = (_f = video.Representation) == null ? void 0 : _f[0].SegmentList) == null ? void 0 : _g.duration).toBe(2);
|
|
50619
50898
|
expect((_h = video.Representation) == null ? void 0 : _h[0].parent).toBe(video);
|
|
50620
50899
|
expect((_i = video.Representation) == null ? void 0 : _i[1].SegmentList).toBeUndefined();
|
|
50621
|
-
expect((_j =
|
|
50900
|
+
expect((_j = period2.AdaptationSet) == null ? void 0 : _j[0].parent).toBe(period2);
|
|
50622
50901
|
});
|
|
50623
50902
|
it("removes elements whose fragment is empty", async () => {
|
|
50624
50903
|
var _a3;
|
|
@@ -50633,10 +50912,10 @@ x`);
|
|
|
50633
50912
|
</Period>
|
|
50634
50913
|
<Period id="zero" duration="PT0S"><ImportedMPD>zero.mpd</ImportedMPD></Period>`)
|
|
50635
50914
|
);
|
|
50636
|
-
const [
|
|
50637
|
-
expect(
|
|
50638
|
-
expect(
|
|
50639
|
-
expect((_a3 =
|
|
50915
|
+
const [period2, zero] = manifest3.MPD.Period;
|
|
50916
|
+
expect(period2.SegmentList).toBeUndefined();
|
|
50917
|
+
expect(period2.EventStream).toEqual([]);
|
|
50918
|
+
expect((_a3 = period2.AdaptationSet) == null ? void 0 : _a3.length).toBe(1);
|
|
50640
50919
|
expect(zero.id).toBe("zero");
|
|
50641
50920
|
});
|
|
50642
50921
|
it("imports a Period without AdaptationSets", async () => {
|
|
@@ -52314,7 +52593,7 @@ x`);
|
|
|
52314
52593
|
// test/unit/track/dash/util/uriResolution.test.ts
|
|
52315
52594
|
describe("resolveDashUri", () => {
|
|
52316
52595
|
let manifest3;
|
|
52317
|
-
let
|
|
52596
|
+
let period2;
|
|
52318
52597
|
let adaptationSet;
|
|
52319
52598
|
let representation;
|
|
52320
52599
|
let deps;
|
|
@@ -52324,13 +52603,13 @@ x`);
|
|
|
52324
52603
|
baseUrlSelector: pickFirstBaseUrlSelector
|
|
52325
52604
|
};
|
|
52326
52605
|
manifest3 = clone(mockDashManifest);
|
|
52327
|
-
|
|
52328
|
-
adaptationSet =
|
|
52606
|
+
period2 = manifest3.MPD.Period[0];
|
|
52607
|
+
adaptationSet = period2.AdaptationSet[0];
|
|
52329
52608
|
representation = adaptationSet.Representation[0];
|
|
52330
52609
|
});
|
|
52331
52610
|
function setBaseUrls(mpdUri, periodUri, adaptationSetUri, representationUri) {
|
|
52332
52611
|
manifest3.MPD.BaseURL = mpdUri ? [{ _content: mpdUri }] : [];
|
|
52333
|
-
|
|
52612
|
+
period2.BaseURL = periodUri ? [{ _content: periodUri }] : [];
|
|
52334
52613
|
adaptationSet.BaseURL = adaptationSetUri ? [{ _content: adaptationSetUri }] : [];
|
|
52335
52614
|
representation.BaseURL = representationUri ? [{ _content: representationUri }] : [];
|
|
52336
52615
|
}
|
|
@@ -52419,7 +52698,7 @@ x`);
|
|
|
52419
52698
|
manifest3.MPD.BaseURL = [
|
|
52420
52699
|
{ _content: "", serviceLocation: "mpdLevel" }
|
|
52421
52700
|
];
|
|
52422
|
-
|
|
52701
|
+
period2.BaseURL = [{ _content: "", serviceLocation: "periodLevel" }];
|
|
52423
52702
|
representation.BaseURL = [
|
|
52424
52703
|
{ _content: "", serviceLocation: "representationLevel" }
|
|
52425
52704
|
];
|
|
@@ -53988,7 +54267,8 @@ x`);
|
|
|
53988
54267
|
type: "hls",
|
|
53989
54268
|
manifestProvider
|
|
53990
54269
|
});
|
|
53991
|
-
const
|
|
54270
|
+
const container = createContainer(factories);
|
|
54271
|
+
const deps = container.dependencies;
|
|
53992
54272
|
expect(deps).toEqual(
|
|
53993
54273
|
objectContaining20({
|
|
53994
54274
|
segmentRequestInit: void 0,
|
|
@@ -54001,6 +54281,7 @@ x`);
|
|
|
54001
54281
|
qualitySelector: any27(QualitySelectorImpl)
|
|
54002
54282
|
})
|
|
54003
54283
|
);
|
|
54284
|
+
container.dispose();
|
|
54004
54285
|
});
|
|
54005
54286
|
it("wires per-track option observables from the player options", () => {
|
|
54006
54287
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54009,11 +54290,13 @@ x`);
|
|
|
54009
54290
|
type: "hls",
|
|
54010
54291
|
manifestProvider
|
|
54011
54292
|
});
|
|
54012
|
-
const
|
|
54293
|
+
const container = createContainer(factories);
|
|
54294
|
+
const deps = container.dependencies;
|
|
54013
54295
|
const options2 = hlsFactoryDeps.options.value;
|
|
54014
54296
|
expect(deps.audio.value).toBe(options2.audio);
|
|
54015
54297
|
expect(deps.allowedContentTypes.value).toBe(options2.allowedContentTypes);
|
|
54016
54298
|
expect(deps.abr.value).toBe(options2.abr);
|
|
54299
|
+
container.dispose();
|
|
54017
54300
|
});
|
|
54018
54301
|
it("exposes the shared adController without owning it", () => {
|
|
54019
54302
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54044,8 +54327,10 @@ x`);
|
|
|
54044
54327
|
type: "hls",
|
|
54045
54328
|
manifestProvider
|
|
54046
54329
|
});
|
|
54047
|
-
const
|
|
54330
|
+
const container = createContainer(factories);
|
|
54331
|
+
const deps = container.dependencies;
|
|
54048
54332
|
expect(deps.contentStreamFactory("audio")).toEqual(any27(Object));
|
|
54333
|
+
container.dispose();
|
|
54049
54334
|
});
|
|
54050
54335
|
it("uses createUrlHlsManifestProvider when no manifestProvider given", () => {
|
|
54051
54336
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54053,8 +54338,10 @@ x`);
|
|
|
54053
54338
|
uri: "https://example.com/main.m3u8",
|
|
54054
54339
|
type: "hls"
|
|
54055
54340
|
});
|
|
54056
|
-
const
|
|
54341
|
+
const container = createContainer(factories);
|
|
54342
|
+
const deps = container.dependencies;
|
|
54057
54343
|
expect(deps.manifestController).toEqual(any27(ManifestControllerImpl));
|
|
54344
|
+
container.dispose();
|
|
54058
54345
|
});
|
|
54059
54346
|
it("creates a sidecar text track controller and populates from manifest", async () => {
|
|
54060
54347
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54079,13 +54366,15 @@ x`);
|
|
|
54079
54366
|
type: "hls",
|
|
54080
54367
|
manifestProvider: provider
|
|
54081
54368
|
});
|
|
54082
|
-
const
|
|
54369
|
+
const container = createContainer(factories);
|
|
54370
|
+
const deps = container.dependencies;
|
|
54083
54371
|
const controller = deps.textTrackController;
|
|
54084
54372
|
await deps.manifestTransformed.value;
|
|
54085
54373
|
await new Promise((r) => setTimeout(r, 0));
|
|
54086
54374
|
expect(controller).toBeDefined();
|
|
54087
54375
|
expect(controller.textTracks.length).toBe(1);
|
|
54088
54376
|
expect(controller.textTracks[0].language).toBe("en");
|
|
54377
|
+
container.dispose();
|
|
54089
54378
|
});
|
|
54090
54379
|
it("text track controller swallows manifest fetch errors", async () => {
|
|
54091
54380
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54097,11 +54386,13 @@ x`);
|
|
|
54097
54386
|
type: "hls",
|
|
54098
54387
|
manifestProvider: provider
|
|
54099
54388
|
});
|
|
54100
|
-
const
|
|
54389
|
+
const container = createContainer(factories);
|
|
54390
|
+
const deps = container.dependencies;
|
|
54101
54391
|
const controller = deps.textTrackController;
|
|
54102
54392
|
await deps.manifestTransformed.value.catch(() => void 0);
|
|
54103
54393
|
await new Promise((r) => setTimeout(r, 0));
|
|
54104
54394
|
expect(controller.textTracks).toEqual([]);
|
|
54395
|
+
container.dispose();
|
|
54105
54396
|
});
|
|
54106
54397
|
describe("ad interstitial discovery", () => {
|
|
54107
54398
|
function interstitialManifest(overrides = {}) {
|
|
@@ -54132,11 +54423,13 @@ x`);
|
|
|
54132
54423
|
type: "hls",
|
|
54133
54424
|
manifestProvider: provider
|
|
54134
54425
|
});
|
|
54135
|
-
const
|
|
54426
|
+
const container = createContainer(factories);
|
|
54427
|
+
const deps = container.dependencies;
|
|
54136
54428
|
const timeline = await deps.mediaTimeline.value;
|
|
54137
54429
|
const adBreaks = await timeline.getAdBreaks();
|
|
54138
54430
|
expect(adBreaks.length).toBe(1);
|
|
54139
54431
|
expect(adBreaks[0].id).toBe("ad1");
|
|
54432
|
+
container.dispose();
|
|
54140
54433
|
});
|
|
54141
54434
|
it("merges stitched SCTE-35 breaks with interstitials by start time", async () => {
|
|
54142
54435
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54177,7 +54470,8 @@ x`);
|
|
|
54177
54470
|
type: "hls",
|
|
54178
54471
|
manifestProvider: provider
|
|
54179
54472
|
});
|
|
54180
|
-
const
|
|
54473
|
+
const container = createContainer(factories);
|
|
54474
|
+
const deps = container.dependencies;
|
|
54181
54475
|
const timeline = await deps.mediaTimeline.value;
|
|
54182
54476
|
const adBreaks = await timeline.getAdBreaks();
|
|
54183
54477
|
expect(
|
|
@@ -54186,6 +54480,7 @@ x`);
|
|
|
54186
54480
|
["splice-1", 2, "stitched"],
|
|
54187
54481
|
["ad1", 11, "interstitial"]
|
|
54188
54482
|
]);
|
|
54483
|
+
container.dispose();
|
|
54189
54484
|
});
|
|
54190
54485
|
it("omits ad breaks when the playlist has none", async () => {
|
|
54191
54486
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54194,9 +54489,11 @@ x`);
|
|
|
54194
54489
|
type: "hls",
|
|
54195
54490
|
manifestProvider
|
|
54196
54491
|
});
|
|
54197
|
-
const
|
|
54492
|
+
const container = createContainer(factories);
|
|
54493
|
+
const deps = container.dependencies;
|
|
54198
54494
|
const timeline = await deps.mediaTimeline.value;
|
|
54199
54495
|
expect(await timeline.getAdBreaks()).toEqual([]);
|
|
54496
|
+
container.dispose();
|
|
54200
54497
|
});
|
|
54201
54498
|
it("discovers ads against a live (non-ended) playlist", async () => {
|
|
54202
54499
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54208,9 +54505,11 @@ x`);
|
|
|
54208
54505
|
type: "hls",
|
|
54209
54506
|
manifestProvider: provider
|
|
54210
54507
|
});
|
|
54211
|
-
const
|
|
54508
|
+
const container = createContainer(factories);
|
|
54509
|
+
const deps = container.dependencies;
|
|
54212
54510
|
const timeline = await deps.mediaTimeline.value;
|
|
54213
54511
|
expect((await timeline.getAdBreaks()).length).toBe(1);
|
|
54512
|
+
container.dispose();
|
|
54214
54513
|
});
|
|
54215
54514
|
it("returns no ad breaks when there are no variants", async () => {
|
|
54216
54515
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54226,9 +54525,11 @@ x`);
|
|
|
54226
54525
|
type: "hls",
|
|
54227
54526
|
manifestProvider: provider
|
|
54228
54527
|
});
|
|
54229
|
-
const
|
|
54528
|
+
const container = createContainer(factories);
|
|
54529
|
+
const deps = container.dependencies;
|
|
54230
54530
|
const timeline = await deps.mediaTimeline.value;
|
|
54231
54531
|
expect(await timeline.getAdBreaks()).toEqual([]);
|
|
54532
|
+
container.dispose();
|
|
54232
54533
|
});
|
|
54233
54534
|
it("surfaces media playlist fetch errors from getAdBreaks", async () => {
|
|
54234
54535
|
const factoryCreator = createHlsFactories(null);
|
|
@@ -54242,11 +54543,13 @@ x`);
|
|
|
54242
54543
|
type: "hls",
|
|
54243
54544
|
manifestProvider: provider
|
|
54244
54545
|
});
|
|
54245
|
-
const
|
|
54546
|
+
const container = createContainer(factories);
|
|
54547
|
+
const deps = container.dependencies;
|
|
54246
54548
|
const timeline = await deps.mediaTimeline.value;
|
|
54247
54549
|
await expectAsync(timeline.getAdBreaks()).toBeRejectedWithError(
|
|
54248
54550
|
"media down"
|
|
54249
54551
|
);
|
|
54552
|
+
container.dispose();
|
|
54250
54553
|
});
|
|
54251
54554
|
});
|
|
54252
54555
|
});
|
|
@@ -59738,10 +60041,11 @@ x`);
|
|
|
59738
60041
|
let player;
|
|
59739
60042
|
beforeEach(() => {
|
|
59740
60043
|
base = createMockVinylDependencies();
|
|
59741
|
-
|
|
59742
|
-
|
|
60044
|
+
depFactories = __spreadProps(__spreadValues({}, externalDependencies(base)), {
|
|
60045
|
+
adController: () => adController = new AdControllerImpl({
|
|
60046
|
+
playbackController: base.playbackController
|
|
60047
|
+
})
|
|
59743
60048
|
});
|
|
59744
|
-
depFactories = externalDependencies(__spreadProps(__spreadValues({}, base), { adController }));
|
|
59745
60049
|
player = createVinylPlayer(
|
|
59746
60050
|
{ media: new MockHTMLAudioElement() },
|
|
59747
60051
|
depFactories
|
|
@@ -60682,6 +60986,34 @@ x`);
|
|
|
60682
60986
|
}
|
|
60683
60987
|
});
|
|
60684
60988
|
|
|
60989
|
+
// test/integ/errata/mseChangeTypeSequence.test.ts
|
|
60990
|
+
var WEBKIT_CHANGE_TYPE_SEQUENCE_BUG = "https://bugs.webkit.org/show_bug.cgi?id=327788";
|
|
60991
|
+
async function loadTestBed() {
|
|
60992
|
+
if (!window.runChangeTypeSequenceRepro) {
|
|
60993
|
+
await new Promise((resolve, reject) => {
|
|
60994
|
+
const script = document.createElement("script");
|
|
60995
|
+
script.src = "errata/mse-changetype-sequence.js";
|
|
60996
|
+
script.onload = () => resolve();
|
|
60997
|
+
script.onerror = () => reject(new Error(`failed to load ${script.src}`));
|
|
60998
|
+
document.head.append(script);
|
|
60999
|
+
});
|
|
61000
|
+
}
|
|
61001
|
+
return window.runChangeTypeSequenceRepro;
|
|
61002
|
+
}
|
|
61003
|
+
describe("errata", () => {
|
|
61004
|
+
it("continues the buffered media after changeType() in sequence mode", async () => {
|
|
61005
|
+
const result = await (await loadTestBed())();
|
|
61006
|
+
if (!result.supported)
|
|
61007
|
+
pending("changeType() or its codecs are not supported");
|
|
61008
|
+
if (!result.contiguous && hasBrowser("WebKit" /* WEBKIT */)) {
|
|
61009
|
+
pending(
|
|
61010
|
+
`WebKit appends at the media time after changeType(): ${WEBKIT_CHANGE_TYPE_SEQUENCE_BUG} ${JSON.stringify(result)}`
|
|
61011
|
+
);
|
|
61012
|
+
}
|
|
61013
|
+
expect(result.after).withContext(JSON.stringify(result)).toEqual([[result.before[0][0], result.before[0][1] + 2]]);
|
|
61014
|
+
});
|
|
61015
|
+
});
|
|
61016
|
+
|
|
60685
61017
|
// test/integ/event/looped.test.ts
|
|
60686
61018
|
describe("looped integ", () => {
|
|
60687
61019
|
const suite = createVinylSuite();
|
|
@@ -60995,15 +61327,19 @@ x`);
|
|
|
60995
61327
|
timeout: 5,
|
|
60996
61328
|
timeoutMessage: "waiting after seek to unbuffered region timed out after {time}s"
|
|
60997
61329
|
});
|
|
60998
|
-
|
|
60999
|
-
|
|
61000
|
-
|
|
61001
|
-
|
|
61002
|
-
|
|
61003
|
-
|
|
61004
|
-
|
|
61005
|
-
|
|
61006
|
-
|
|
61330
|
+
await Promise.all([
|
|
61331
|
+
player.seekTo(22),
|
|
61332
|
+
// unbuffered region
|
|
61333
|
+
(async () => {
|
|
61334
|
+
await nextWaiting;
|
|
61335
|
+
nextWaited = waitedSpy.next(
|
|
61336
|
+
5,
|
|
61337
|
+
"waited after data buffered 2 timed out after {timeout}s"
|
|
61338
|
+
);
|
|
61339
|
+
await mediaSource.appendNext();
|
|
61340
|
+
await nextWaited;
|
|
61341
|
+
})()
|
|
61342
|
+
]);
|
|
61007
61343
|
});
|
|
61008
61344
|
});
|
|
61009
61345
|
});
|
|
@@ -61105,21 +61441,17 @@ x`);
|
|
|
61105
61441
|
describe("PlaybackControllerImpl integ", () => {
|
|
61106
61442
|
let media;
|
|
61107
61443
|
let controller;
|
|
61108
|
-
let originalMuted;
|
|
61109
61444
|
setTestTimeout(25);
|
|
61110
61445
|
beforeEach(() => {
|
|
61111
61446
|
media = mediaRef.value;
|
|
61112
|
-
|
|
61113
|
-
if (!media.muted) {
|
|
61114
|
-
media.muted = true;
|
|
61115
|
-
}
|
|
61447
|
+
media.muted = true;
|
|
61116
61448
|
controller = new PlaybackControllerImpl({
|
|
61117
61449
|
media,
|
|
61118
61450
|
loudnessNormalizationController: new MockLoudnessNormalizationController()
|
|
61119
61451
|
});
|
|
61120
61452
|
});
|
|
61121
61453
|
afterEach(() => {
|
|
61122
|
-
media.muted =
|
|
61454
|
+
media.muted = false;
|
|
61123
61455
|
controller.dispose();
|
|
61124
61456
|
});
|
|
61125
61457
|
describe("mutedChange", () => {
|
|
@@ -61592,6 +61924,58 @@ x`);
|
|
|
61592
61924
|
});
|
|
61593
61925
|
});
|
|
61594
61926
|
|
|
61927
|
+
// test/integ/track/dash/periodCodecChange.test.ts
|
|
61928
|
+
var SEGMENTS_BASE = "https://assets.dev.vinyl.music.amazon.dev/dash/vinyl_ad_breaks_av/segments/";
|
|
61929
|
+
function period(id, start, rendition, codecs, startNumber, mediaStart) {
|
|
61930
|
+
const timescale = 15360;
|
|
61931
|
+
const t = mediaStart * timescale;
|
|
61932
|
+
return `
|
|
61933
|
+
<Period id="${id}" start="PT${start}S" duration="PT8S">
|
|
61934
|
+
<AdaptationSet contentType="video" mimeType="video/mp4" segmentAlignment="true">
|
|
61935
|
+
<Representation id="${id}-video" bandwidth="1000000" codecs="${codecs}" width="640" height="360">
|
|
61936
|
+
<SegmentTemplate timescale="${timescale}" initialization="${rendition}/init.mp4" media="${rendition}/part_$Number$.m4s" startNumber="${startNumber}" presentationTimeOffset="${t}">
|
|
61937
|
+
<SegmentTimeline><S t="${t}" d="30720" r="3"/></SegmentTimeline>
|
|
61938
|
+
</SegmentTemplate>
|
|
61939
|
+
</Representation>
|
|
61940
|
+
</AdaptationSet>
|
|
61941
|
+
</Period>`;
|
|
61942
|
+
}
|
|
61943
|
+
var PERIOD_CODEC_CHANGE_MPD = `<?xml version="1.0" encoding="UTF-8"?>
|
|
61944
|
+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" minBufferTime="PT2S" mediaPresentationDuration="PT16S">
|
|
61945
|
+
${period("first", 0, "libx264_640x360_30fps_600k", "avc1.64001e", 1, 0)}
|
|
61946
|
+
${period("second", 8, "libx264_1280x720_30fps_1500k", "avc1.64001f", 31, 60)}
|
|
61947
|
+
</MPD>`;
|
|
61948
|
+
describe("dash Period codec change integ", () => {
|
|
61949
|
+
const suite = createVinylSuite({}, { timeout: 60 });
|
|
61950
|
+
beforeEach(() => {
|
|
61951
|
+
if (!supportsMse()) pending("MSE not supported");
|
|
61952
|
+
if (!("changeType" in SourceBuffer.prototype))
|
|
61953
|
+
pending("SourceBuffer.changeType not supported");
|
|
61954
|
+
});
|
|
61955
|
+
const loadOptions = {
|
|
61956
|
+
type: "dash",
|
|
61957
|
+
uri: "test://period-codec-change",
|
|
61958
|
+
manifestProvider: () => Promise.resolve({
|
|
61959
|
+
manifest: parseDashManifest(PERIOD_CODEC_CHANGE_MPD),
|
|
61960
|
+
baseUrl: SEGMENTS_BASE
|
|
61961
|
+
})
|
|
61962
|
+
};
|
|
61963
|
+
it("plays across a Period boundary that changes codec", async () => {
|
|
61964
|
+
const changeType = spyOn(
|
|
61965
|
+
SourceBuffer.prototype,
|
|
61966
|
+
"changeType"
|
|
61967
|
+
).and.callThrough();
|
|
61968
|
+
const player = suite.player;
|
|
61969
|
+
player.load(loadOptions);
|
|
61970
|
+
await player.play().catch(() => void 0);
|
|
61971
|
+
await player.seekTo(6, 0.5).catch(() => void 0);
|
|
61972
|
+
expect(await poll(() => player.currentTime >= 10, { timeout: 20 })).withContext(`plays past the boundary (at ${player.currentTime})`).toBeTrue();
|
|
61973
|
+
expect(changeType).toHaveBeenCalledWith(
|
|
61974
|
+
'video/mp4; codecs="avc1.64001f"'
|
|
61975
|
+
);
|
|
61976
|
+
});
|
|
61977
|
+
});
|
|
61978
|
+
|
|
61595
61979
|
// test/integ/track/dash/Uhd.test.ts
|
|
61596
61980
|
describe("uhd integ", () => {
|
|
61597
61981
|
class ForceUhdCapabilities extends CapabilitiesImpl {
|