@amazon/vinyl 3.2.0 → 3.2.2
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 +65 -45
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +90 -69
- package/dist/index.js.map +3 -3
- package/dist/test/integ.es5.js +303 -287
- package/dist/test/integ.js +328 -71
- package/dist/test/integ.js.map +2 -2
- package/dist/types/current/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.js +42 -20
- 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/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
- package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
- package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -1
- package/dist/types/current/playback/createStallMonitor.js +19 -14
- 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/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +110 -4
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
- package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.js +38 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/index.js +10 -1
- package/dist/vinylTestUtil/index.js.map +2 -2
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.js +9 -0
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/ts3.7/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/ts4.1/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/ts4.7/assets/vinylTestAssets.d.ts +5 -0
- package/package.json +10 -10
|
@@ -7,6 +7,15 @@ import type { AdsProvider } from './AdsProvider';
|
|
|
7
7
|
* The % playhead start tolerance for playback progress when emitting ad progress events.
|
|
8
8
|
*/
|
|
9
9
|
export declare const AD_START_TOLERANCE = 0.05;
|
|
10
|
+
/**
|
|
11
|
+
* When a break's X-PLAYOUT-LIMIT budget is reached, an ad whose real media end is
|
|
12
|
+
* within this many seconds is allowed to finish on its own `ended` rather than
|
|
13
|
+
* being cut. The limit is a coarse, often whole-second budget while the media's
|
|
14
|
+
* true length is fractional, so without this grace an ad effectively as long as
|
|
15
|
+
* its budget would be clipped a fraction short. The tolerance is measured against
|
|
16
|
+
* the playback-reported (media) duration, not the ad's declared duration.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
10
19
|
export interface AdControllerImplDeps {
|
|
11
20
|
readonly playbackController: ReadonlyPlaybackController;
|
|
12
21
|
}
|
|
@@ -129,8 +138,15 @@ export declare class AdControllerImpl extends EventHostImpl<AdEventMap> implemen
|
|
|
129
138
|
private emitAdProgressEvents;
|
|
130
139
|
private emitTimeUpdate;
|
|
131
140
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
141
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
142
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
143
|
+
* whole break ends, dropping any ads that have not started.
|
|
144
|
+
*
|
|
145
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
146
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
147
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
148
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
149
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
134
150
|
*/
|
|
135
151
|
private enforcePlayoutLimits;
|
|
136
152
|
private setPendingBreaks;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/ad/AdControllerImpl.ts"],"names":[],"mappings":"AAKA,OAAO,EAGH,aAAa,EAehB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,KAAK,WAAW,EAEhB,KAAK,MAAM,EACX,KAAK,QAAQ,EAChB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAER,YAAY,EACZ,UAAU,EAEb,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAA;AAExF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD;;GAEG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,kBAAkB,EAAE,0BAA0B,CAAA;CAC1D;AAED,MAAM,WAAW,uBAAuB;IACpC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CACpC;AAED,eAAO,MAAM,8BAA8B,EAAE,uBAG5C,CAAA;AA2CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBACT,SAAQ,aAAa,CAAC,UAAU,CAChC,YAAW,YAAY;IAkCnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhCzB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAEjC;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,cAAc,CAA2B;IACjD,OAAO,CAAC,WAAW,CAA2B;IAE9C,OAAO,CAAC,UAAU,CAAkB;IAGpC,OAAO,CAAC,iBAAiB,CAAkB;IAI3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;IAE1D,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,eAAe,CAAoB;IAG3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAwB;IAI3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAQ;gBAGN,IAAI,EAAE,oBAAoB,EAC3C,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC;IAuD9C,iBAAiB,IAAI,IAAI;IAMzB,OAAO,CAAC,iBAAiB;IAKzB,8EAA8E;IAC9E,OAAO,CAAC,SAAS;IAUjB;;;;;OAKG;YACW,gBAAgB;IAwB9B,IAAI,eAAe,IAAI,QAAQ,GAAG,IAAI,CAErC;IAED,OAAO,CAAC,WAAW;IAqBnB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAK3B,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI;IAkC5C,YAAY,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAI3C,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;YAIpC,SAAS;IAgCvB,OAAO,KAAK,WAAW,GAEtB;IAED,WAAW,IAAI,IAAI;IAWnB;;OAEG;IACH,OAAO,CAAC,eAAe;IA4CvB,IAAI,cAAc,IAAI,WAAW,GAAG,IAAI,CAEvC;IAED;;OAEG;IACH,OAAO,CAAC,UAAU;IAqBlB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAsErB,IAAI,SAAS,IAAI,MAAM,GAAG,IAAI,CAE7B;IAED,OAAO,KAAK,OAAO,GAElB;IAED,OAAO,CAAC,OAAO;IAwBf;;OAEG;IACH,OAAO,CAAC,YAAY,CAkBnB;IAED;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgC3B;;;;OAIG;YACW,oBAAoB;YAyCpB,cAAc;IA+C5B
|
|
1
|
+
{"version":3,"file":"AdControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/ad/AdControllerImpl.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,15 @@ import { AdError } from './AdError';
|
|
|
8
8
|
* The % playhead start tolerance for playback progress when emitting ad progress events.
|
|
9
9
|
*/
|
|
10
10
|
export const AD_START_TOLERANCE = 0.05;
|
|
11
|
+
/**
|
|
12
|
+
* When a break's X-PLAYOUT-LIMIT budget is reached, an ad whose real media end is
|
|
13
|
+
* within this many seconds is allowed to finish on its own `ended` rather than
|
|
14
|
+
* being cut. The limit is a coarse, often whole-second budget while the media's
|
|
15
|
+
* true length is fractional, so without this grace an ad effectively as long as
|
|
16
|
+
* its budget would be clipped a fraction short. The tolerance is measured against
|
|
17
|
+
* the playback-reported (media) duration, not the ad's declared duration.
|
|
18
|
+
*/
|
|
19
|
+
export const PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
11
20
|
export const defaultAdControllerImplOptions = {
|
|
12
21
|
adLoadTimeout: 15,
|
|
13
22
|
preloadAheadTime: 10,
|
|
@@ -560,30 +569,43 @@ export class AdControllerImpl extends EventHostImpl {
|
|
|
560
569
|
});
|
|
561
570
|
}
|
|
562
571
|
/**
|
|
563
|
-
*
|
|
564
|
-
*
|
|
572
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
573
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
574
|
+
* whole break ends, dropping any ads that have not started.
|
|
575
|
+
*
|
|
576
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
577
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
578
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
579
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
580
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
565
581
|
*/
|
|
566
582
|
enforcePlayoutLimits(adState) {
|
|
583
|
+
if (!adState.started)
|
|
584
|
+
return;
|
|
585
|
+
const { parentBreak } = adState;
|
|
586
|
+
// Enforce independent of a finite content duration so live ads with a
|
|
587
|
+
// declared playout limit are still bounded.
|
|
588
|
+
const limit = parentBreak.adBreak.playoutLimit;
|
|
589
|
+
if (limit == null)
|
|
590
|
+
return;
|
|
567
591
|
const pC = this.deps.playbackController;
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
if
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
this.endAd(adState);
|
|
581
|
-
}
|
|
582
|
-
else if (ad.duration != null && elapsed >= ad.duration) {
|
|
583
|
-
// This ad reached its declared duration: advance to the next.
|
|
584
|
-
this.endAd(adState);
|
|
585
|
-
}
|
|
592
|
+
const elapsed = Math.max(0, pC.currentTime - adState.timeStart);
|
|
593
|
+
if (parentBreak.playoutElapsed + elapsed < limit)
|
|
594
|
+
return;
|
|
595
|
+
// Budget reached — but if the current ad is essentially at its natural
|
|
596
|
+
// media end (within PLAYOUT_LIMIT_TOLERANCE of the playback-reported
|
|
597
|
+
// duration), let it finish on its own `ended` rather than clipping the
|
|
598
|
+
// tail. A known finite, positive duration is required; an unknown (0) or
|
|
599
|
+
// non-finite duration (e.g. live) enforces the limit strictly.
|
|
600
|
+
if (isFinite(pC.duration) &&
|
|
601
|
+
pC.duration > 0 &&
|
|
602
|
+
pC.duration - pC.currentTime <= PLAYOUT_LIMIT_TOLERANCE) {
|
|
603
|
+
return;
|
|
586
604
|
}
|
|
605
|
+
// The break's total playout limit is reached: end the whole break,
|
|
606
|
+
// dropping any ads that have not started.
|
|
607
|
+
parentBreak.clear();
|
|
608
|
+
this.endAd(adState);
|
|
587
609
|
}
|
|
588
610
|
setPendingBreaks(newPending) {
|
|
589
611
|
this.pendingAdBreaks = newPending.filter((adBreak) => !this.isBreakSuppressed(adBreak));
|
|
@@ -12,6 +12,12 @@ import type { TrackUri } from '../track/Track';
|
|
|
12
12
|
* indicates a stalled promise result from the license provider.
|
|
13
13
|
*/
|
|
14
14
|
export declare const LICENSE_TIMEOUT = 90;
|
|
15
|
+
/**
|
|
16
|
+
* An excessive number of concurrent key sessions. Sessions are expected to be
|
|
17
|
+
* closed as tracks deactivate; a count this high signals sessions are leaking
|
|
18
|
+
* (never closing) rather than a legitimate playback need.
|
|
19
|
+
*/
|
|
20
|
+
export declare const EXCESSIVE_SESSION_COUNT = 20;
|
|
15
21
|
/**
|
|
16
22
|
* Dependencies for creating DrmController.
|
|
17
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrmControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/drm/DrmControllerImpl.ts"],"names":[],"mappings":"AAKA,OAAO,EAUH,aAAa,
|
|
1
|
+
{"version":3,"file":"DrmControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/drm/DrmControllerImpl.ts"],"names":[],"mappings":"AAKA,OAAO,EAUH,aAAa,EAOb,KAAK,KAAK,EAUb,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAEH,KAAK,UAAU,EAGlB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EACR,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EACrB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EACR,SAAS,EAET,0BAA0B,EAC1B,eAAe,EACf,qBAAqB,EAExB,MAAM,uBAAuB,CAAA;AAK9B,OAAO,KAAK,EACR,WAAW,EACX,mBAAmB,EACtB,MAAM,mCAAmC,CAAA;AAS1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,KAAK,CAAA;AAGjC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAEzC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,yBAAyB;IACtC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAA;IACvC,QAAQ,CAAC,KAAK,EAAE,0BAA0B,CAAA;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IAClC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAC3C;AAyBD,qBAAa,iBACT,SAAQ,aAAa,CAAC,qBAAqB,CAC3C,YAAW,aAAa;IA4BpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IA1BzB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAEjC;IAED,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAY;IACxC,OAAO,CAAC,OAAO,CAAY;IAE3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,gBAAgB,CAAwC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IAEvD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,iBAAiB,CAAwB;IACjD,OAAO,CAAC,YAAY,CAA6B;IAEjD,OAAO,CAAC,mBAAmB,CAAyC;IAIpE,OAAO,CAAC,iBAAiB,CAAO;IAChC,OAAO,CAAC,iBAAiB,CAAyB;IAElD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;gBAGvB,IAAI,EAAE,qBAAqB,EAC5C,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAgBxC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI;IAWpD,OAAO,KAAK,eAAe,GAE1B;IAED,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,CAExB;IAED,cAAc,IAAI,OAAO;IAInB,WAAW,CACb,OAAO,EAAE,mBAAmB,GAC7B,OAAO,CAAC,mBAAmB,CAAC;IAS/B,OAAO,CAAC,sBAAsB,CAgC7B;IAED,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CA2CpC;IAED;;;OAGG;YACW,eAAe;IAsB7B;;;;OAIG;YACW,kBAAkB;IAwEhC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAsBxB,qBAAqB,CACjB,OAAO,EAAE,mBAAmB,GAAG,IAAI,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC7B,IAAI;IAWP,+EAA+E;IAC/E,OAAO,CAAC,wBAAwB;IAOhC,mBAAmB,CACf,OAAO,EAAE,mBAAmB,GAAG,IAAI,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC7B,IAAI;IAYP;;;OAGG;YACW,yBAAyB;IAkCvC;;OAEG;YACW,YAAY;IAmC1B;;OAEG;IACH,OAAO,CAAC,gCAAgC;IAyDxC,OAAO,CAAC,wBAAwB;IAiBhC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmCxB;;OAEG;YACW,cAAc;IAoE5B;;;OAGG;IACH,aAAa;IAKb,OAAO,CAAC,YAAY;IAcpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAM3B;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB,SAAS,CAAC,eAAe;IAIzB,KAAK;IA2BL,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,oBAAoB;IAU5B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CASnC;CACJ"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { AbortError, base64ToByteArray, buffersEqual, bufferToByteArray, clone, compareBy, createDisposer, ErrorOrigin, EventHostImpl, getUserAgentInfo, isSilentError, logDebug, logError, logVerbose, memoize, noop, normalizeHeadersInit, Os, remove, resolveValueProvider, withTimeout, } from '@amazon/vinyl-util';
|
|
5
|
+
import { AbortError, base64ToByteArray, buffersEqual, bufferToByteArray, clone, compareBy, createDisposer, ErrorOrigin, EventHostImpl, getUserAgentInfo, isSilentError, logDebug, logError, logVerbose, logWarn, memoize, noop, normalizeHeadersInit, Os, remove, resolveValueProvider, withTimeout, } from '@amazon/vinyl-util';
|
|
6
6
|
import { instanceOf, object } from '@amazon/vinyl-validation';
|
|
7
7
|
import { DrmRobustness, } from './DrmOptions';
|
|
8
8
|
import { DrmError } from './error/DrmError';
|
|
@@ -20,6 +20,12 @@ import { createFairPlaySessionInitData } from './util/createFairPlaySessionInitD
|
|
|
20
20
|
*/
|
|
21
21
|
export const LICENSE_TIMEOUT = 90;
|
|
22
22
|
const LICENSE_TIMEOUT_MESSAGE = 'License provider timed out after {time}s';
|
|
23
|
+
/**
|
|
24
|
+
* An excessive number of concurrent key sessions. Sessions are expected to be
|
|
25
|
+
* closed as tracks deactivate; a count this high signals sessions are leaking
|
|
26
|
+
* (never closing) rather than a legitimate playback need.
|
|
27
|
+
*/
|
|
28
|
+
export const EXCESSIVE_SESSION_COUNT = 20;
|
|
23
29
|
export class DrmControllerImpl extends EventHostImpl {
|
|
24
30
|
deps;
|
|
25
31
|
get [Symbol.toStringTag]() {
|
|
@@ -196,6 +202,10 @@ export class DrmControllerImpl extends EventHostImpl {
|
|
|
196
202
|
trackUri,
|
|
197
203
|
});
|
|
198
204
|
this.sessions.push(newSession);
|
|
205
|
+
logVerbose(this, `total sessions: ${this.sessions.length}`);
|
|
206
|
+
if (this.sessions.length === EXCESSIVE_SESSION_COUNT + 1) {
|
|
207
|
+
logWarn(this, `${this.sessions.length} open key sessions exceeds ${EXCESSIVE_SESSION_COUNT}; sessions may be leaking (not closing on track deactivation)`);
|
|
208
|
+
}
|
|
199
209
|
this.dispatch('sessionCreate', {
|
|
200
210
|
initDataType: newSession.initDataType,
|
|
201
211
|
mimeType: newSession.mimeType,
|
|
@@ -63,12 +63,11 @@ export declare class PlaybackControllerImpl extends EventHostImpl<PlaybackContro
|
|
|
63
63
|
private _playing;
|
|
64
64
|
private _seeking;
|
|
65
65
|
private _waiting;
|
|
66
|
-
private
|
|
66
|
+
private readonly seekAbortSlot;
|
|
67
67
|
private stopStallDetection;
|
|
68
68
|
private userVolume;
|
|
69
69
|
private _pendingPlay;
|
|
70
70
|
private playAbort;
|
|
71
|
-
private disposeAbort;
|
|
72
71
|
readonly options: PlaybackControllerImplOptions;
|
|
73
72
|
constructor(deps: PlaybackControllerImplDeps, options?: Partial<PlaybackControllerImplOptions>);
|
|
74
73
|
/**
|
|
@@ -174,6 +173,13 @@ export declare class PlaybackControllerImpl extends EventHostImpl<PlaybackContro
|
|
|
174
173
|
get hasMetadata(): boolean;
|
|
175
174
|
get playIsPending(): boolean;
|
|
176
175
|
seekTo(time: number, tolerance?: number): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* The body of a single {@link seekTo} attempt. Extracted so {@link seekTo}
|
|
178
|
+
* can wrap it with per-seek abort/supersession handling. `seekAbort` is
|
|
179
|
+
* aborted when a newer seek supersedes this one (or on dispose).
|
|
180
|
+
* @private
|
|
181
|
+
*/
|
|
182
|
+
private doSeek;
|
|
177
183
|
/**
|
|
178
184
|
* Dispatches a readyStateChange event when {@link readyState} changes.
|
|
179
185
|
* @private
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaybackControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/playback/PlaybackControllerImpl.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"PlaybackControllerImpl.d.ts","sourceRoot":"","sources":["../../../../src/playback/PlaybackControllerImpl.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { Abort, AbortError, Browser, clamp, closeTo, createDisposer, createTimeRangesReader, DomEventHost, ErrorLevel, ErrorOrigin, EventHostImpl, hasBrowser, logDebug, logInfo, logWarn, nextEventAsPromise, noop, onAny, ownKeys, TimeoutSlot, toLowerCase, withAbort, withTimeout, } from '@amazon/vinyl-util';
|
|
5
|
+
import { Abort, AbortError, createAbortSlot, Browser, clamp, closeTo, createDisposer, createTimeRangesReader, DomEventHost, ErrorLevel, ErrorOrigin, EventHostImpl, hasBrowser, logDebug, logInfo, logWarn, nextEventAsPromise, noop, onAny, ownKeys, TimeoutSlot, toLowerCase, withAbort, withTimeout, } from '@amazon/vinyl-util';
|
|
6
6
|
import { LIVE_DURATION } from './PlaybackController';
|
|
7
7
|
import { PlaybackReadyState, playedReasons, waitedReasons, } from './ReadonlyPlaybackController';
|
|
8
8
|
import { createStallDetector } from './createStallDetector';
|
|
@@ -52,15 +52,13 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
52
52
|
_playing = false;
|
|
53
53
|
_seeking = false;
|
|
54
54
|
_waiting = false;
|
|
55
|
-
|
|
56
|
-
_seekId = 0;
|
|
55
|
+
seekAbortSlot = createAbortSlot();
|
|
57
56
|
// Stops the stall detector started after the last seek, if any.
|
|
58
57
|
stopStallDetection = null;
|
|
59
58
|
// default user volume (0.0 to 1.0 scale)
|
|
60
59
|
userVolume = 1.0;
|
|
61
60
|
_pendingPlay = null;
|
|
62
61
|
playAbort = null;
|
|
63
|
-
disposeAbort = new Abort();
|
|
64
62
|
options;
|
|
65
63
|
constructor(deps, options) {
|
|
66
64
|
super();
|
|
@@ -75,8 +73,7 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
75
73
|
this.media = deps.media;
|
|
76
74
|
const { add } = this.disposer;
|
|
77
75
|
add(() => {
|
|
78
|
-
this.
|
|
79
|
-
this.disposeAbort.dispose();
|
|
76
|
+
this.seekAbortSlot.abort();
|
|
80
77
|
this.stopStallDetection?.();
|
|
81
78
|
});
|
|
82
79
|
this.domEvents = add(new DomEventHost(deps.media));
|
|
@@ -471,34 +468,44 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
471
468
|
}
|
|
472
469
|
async seekTo(time, tolerance = 0.5) {
|
|
473
470
|
logDebug(this, `seekTo: ${time}`);
|
|
474
|
-
// Claim this seek as the newest. A seek that parks on an await (e.g. waiting for loadedMetadata) can resume
|
|
475
|
-
// AFTER a later-issued seek has already applied its target.
|
|
476
|
-
const seekId = ++this._seekId;
|
|
477
471
|
// A new seek supersedes any stall watch from the previous one.
|
|
478
472
|
this.stopStallDetection?.();
|
|
479
473
|
this.stopStallDetection = null;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return false;
|
|
483
|
-
logDebug(this, `seekTo: ${time} superseded by a newer seek`);
|
|
484
|
-
return true;
|
|
485
|
-
};
|
|
474
|
+
this.seekAbortSlot.abort();
|
|
475
|
+
const seekAbort = this.seekAbortSlot.value;
|
|
486
476
|
const nextEvent = (type, options) => {
|
|
487
477
|
return nextEventAsPromise(this, type, {
|
|
488
478
|
timeout: options?.timeout ?? this.options.seekTimeout,
|
|
489
479
|
timeoutMessage: `seek timed out on ${type} event after {time}s`,
|
|
490
480
|
timeoutOrigin: ErrorOrigin.INTERNAL,
|
|
491
481
|
timeoutLevel: ErrorLevel.WARN,
|
|
492
|
-
abort:
|
|
482
|
+
abort: seekAbort,
|
|
493
483
|
});
|
|
494
484
|
};
|
|
495
|
-
|
|
485
|
+
try {
|
|
486
|
+
await this.doSeek(time, tolerance, seekAbort, nextEvent);
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
// A newer seek aborted this one's waits: it owns the media element
|
|
490
|
+
// now, so resolve quietly (matching the mid-flight `aborted()`
|
|
491
|
+
// bail-outs). Dispose and any real error still propagate.
|
|
492
|
+
if (seekAbort.aborted() && !this.disposed)
|
|
493
|
+
return;
|
|
494
|
+
throw error;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* The body of a single {@link seekTo} attempt. Extracted so {@link seekTo}
|
|
499
|
+
* can wrap it with per-seek abort/supersession handling. `seekAbort` is
|
|
500
|
+
* aborted when a newer seek supersedes this one (or on dispose).
|
|
501
|
+
* @private
|
|
502
|
+
*/
|
|
503
|
+
async doSeek(time, tolerance, seekAbort, nextEvent) {
|
|
504
|
+
// Cannot seek until there are seekable ranges. If a newer seek supersedes
|
|
505
|
+
// this one while we wait, `seekAbort` rejects this await — the newer seek
|
|
506
|
+
// then owns the target, and this stale one resolves quietly in `seekTo`.
|
|
496
507
|
if (!this.hasMetadata) {
|
|
497
508
|
await nextEvent('loadedMetadata');
|
|
498
|
-
// A newer seek was issued while we waited — it already applied (or
|
|
499
|
-
// will apply) its target. Don't overwrite it with this stale one.
|
|
500
|
-
if (superseded())
|
|
501
|
-
return;
|
|
502
509
|
}
|
|
503
510
|
const seekable = this.seekable;
|
|
504
511
|
const range = seekable.getRangeAt(clamp(time, 0, this.duration), tolerance);
|
|
@@ -520,18 +527,15 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
520
527
|
else {
|
|
521
528
|
// A dispose rejects the seek; a timeout means the attempt is stuck.
|
|
522
529
|
const nullIfStuck = (error) => {
|
|
523
|
-
if (this.
|
|
530
|
+
if (this.disposed)
|
|
524
531
|
throw error;
|
|
525
532
|
return null;
|
|
526
533
|
};
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
// `seeking` (a media that never starts seeking is a real timeout); a
|
|
533
|
-
// re-seek to the current position emits no fresh `seeking` on WebKit,
|
|
534
|
-
// so bound that wait and fall through to the stall detector.
|
|
534
|
+
// One seek attempt; returns the seeked event, or null if it didn't
|
|
535
|
+
// complete in SEEK_ATTEMPT_TIMEOUT. A re-seek to the current position
|
|
536
|
+
// emits no fresh `seeking` on WebKit, so bound that wait; the initial
|
|
537
|
+
// attempt keeps the full seekTimeout (a media that never starts
|
|
538
|
+
// seeking is a real timeout).
|
|
535
539
|
const seekOnce = async (reSeeking) => {
|
|
536
540
|
const seeking = reSeeking
|
|
537
541
|
? nextEvent('seeking', {
|
|
@@ -551,7 +555,7 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
551
555
|
// outside tolerance of the target. Bounded, and not fighting a newer
|
|
552
556
|
// seek. The play() kick is fire-and-forget: a wedged seek can leave
|
|
553
557
|
// its promise unsettled forever, which would stall the retry loop.
|
|
554
|
-
for (let attempt = 0; !
|
|
558
|
+
for (let attempt = 0; !seekAbort.aborted() &&
|
|
555
559
|
attempt < SEEK_RETRY_LIMIT &&
|
|
556
560
|
(seekedEvent === null ||
|
|
557
561
|
(seekedEvent.reason === 'seeked' &&
|
|
@@ -567,8 +571,9 @@ export class PlaybackControllerImpl extends EventHostImpl {
|
|
|
567
571
|
}
|
|
568
572
|
// Some WebKit versions don't resume after seeking. Watch for that:
|
|
569
573
|
// nudge/kick playback back to life, and fabricate a playing event
|
|
570
|
-
// if it resumes without emitting one.
|
|
571
|
-
|
|
574
|
+
// if it resumes without emitting one. Skip when superseded — a newer
|
|
575
|
+
// seek owns the element and arms its own watch.
|
|
576
|
+
if (!this.paused && !seekAbort.aborted())
|
|
572
577
|
this.startStallDetection();
|
|
573
578
|
}
|
|
574
579
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStallMonitor.d.ts","sourceRoot":"","sources":["../../../../src/playback/createStallMonitor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;CACpC;AAED,MAAM,WAAW,qBAAqB;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAA;IACnC,yCAAyC;IACzC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;CACxD;
|
|
1
|
+
{"version":3,"file":"createStallMonitor.d.ts","sourceRoot":"","sources":["../../../../src/playback/createStallMonitor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;CACpC;AAED,MAAM,WAAW,qBAAqB;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAA;IACnC,yCAAyC;IACzC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;CACxD;AASD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAC9B,UAAU,EAAE,0BAA0B,EACtC,SAAS,EAAE,qBAAqB,EAChC,OAAO,GAAE,mBAAwB,GAClC,MAAM,IAAI,CA+EZ"}
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createDisposer } from '@amazon/vinyl-util';
|
|
6
6
|
import { StallEndedReason } from './ReadonlyPlaybackController';
|
|
7
|
+
/**
|
|
8
|
+
* Minimum forward `currentTime` change (seconds) that counts as real progress. Guards the
|
|
9
|
+
* progress check against floating-point jitter so a negligible advance isn't mistaken for the
|
|
10
|
+
* play head moving.
|
|
11
|
+
*/
|
|
12
|
+
const PROGRESS_EPSILON = 1e-6;
|
|
7
13
|
/**
|
|
8
14
|
* Watches a {@link ReadonlyPlaybackController} for stalls while playing: the play head freezing
|
|
9
15
|
* (no `timeUpdate`) for longer than {@link StallMonitorOptions.stallThreshold} seconds.
|
|
@@ -26,6 +32,7 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
26
32
|
let lastProgressAt = Date.now();
|
|
27
33
|
let inStall = false;
|
|
28
34
|
let pollId = null;
|
|
35
|
+
const { add, dispose } = createDisposer();
|
|
29
36
|
const endStall = (reason) => {
|
|
30
37
|
if (!inStall)
|
|
31
38
|
return;
|
|
@@ -44,6 +51,7 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
44
51
|
clearInterval(pollId);
|
|
45
52
|
pollId = null;
|
|
46
53
|
};
|
|
54
|
+
add(stopPoll);
|
|
47
55
|
const startPoll = () => {
|
|
48
56
|
if (pollId != null)
|
|
49
57
|
return;
|
|
@@ -63,18 +71,22 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
63
71
|
observedPlaying = false;
|
|
64
72
|
stopPoll();
|
|
65
73
|
};
|
|
66
|
-
const { add, dispose } = createDisposer();
|
|
67
74
|
add(controller.on('playing', () => {
|
|
68
|
-
// Resuming from a stall closes it
|
|
69
|
-
// begin the freeze clock now (no `timeUpdate` has necessarily arrived yet).
|
|
75
|
+
// Resuming from a stall closes it (using the pre-resume freeze start for its duration).
|
|
70
76
|
if (inStall)
|
|
71
77
|
endStall(StallEndedReason.PLAYING);
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
// Whether resuming or freshly starting, the play head is advancing again, so restart the
|
|
79
|
+
// freeze clock. Without this the poll could immediately re-detect a stall from the stale
|
|
80
|
+
// pre-freeze timestamp before the first post-resume `timeUpdate` resets it.
|
|
81
|
+
lastProgressAt = Date.now();
|
|
74
82
|
observedPlaying = true;
|
|
75
83
|
startPoll();
|
|
76
84
|
}));
|
|
77
|
-
add(controller.on('timeUpdate', () => {
|
|
85
|
+
add(controller.on('timeUpdate', ({ previous, current }) => {
|
|
86
|
+
// Browsers emit `timeUpdate` while frozen (unchanged/backward `currentTime`); only a
|
|
87
|
+
// forward advance is progress, else a stall is ended and re-detected, doubling events.
|
|
88
|
+
if (previous != null && current - previous <= PROGRESS_EPSILON)
|
|
89
|
+
return;
|
|
78
90
|
// The play head advanced: close any open stall, then reset the freeze clock.
|
|
79
91
|
if (inStall)
|
|
80
92
|
endStall(StallEndedReason.PLAYING);
|
|
@@ -83,12 +95,5 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
83
95
|
add(controller.on('pause', () => suspend(StallEndedReason.PAUSE)));
|
|
84
96
|
add(controller.on('seeking', () => suspend(StallEndedReason.SEEKING)));
|
|
85
97
|
add(controller.on('emptied', () => suspend(StallEndedReason.EMPTIED)));
|
|
86
|
-
|
|
87
|
-
return () => {
|
|
88
|
-
if (stopped)
|
|
89
|
-
return;
|
|
90
|
-
stopped = true;
|
|
91
|
-
stopPoll();
|
|
92
|
-
dispose();
|
|
93
|
-
};
|
|
98
|
+
return dispose;
|
|
94
99
|
}
|
|
@@ -45,7 +45,6 @@ export declare class MseTrack extends TrackBase {
|
|
|
45
45
|
protected readonly deps: MseTrackDeps;
|
|
46
46
|
get textTrackController(): TextTrackController | null;
|
|
47
47
|
private readonly streams;
|
|
48
|
-
private readonly disposeAbort;
|
|
49
48
|
private lastPreloadOptions;
|
|
50
49
|
private readonly allFetchedRanges;
|
|
51
50
|
private readonly _fetchedRanges;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MseTrack.d.ts","sourceRoot":"","sources":["../../../../../src/track/mse/MseTrack.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"MseTrack.d.ts","sourceRoot":"","sources":["../../../../../src/track/mse/MseTrack.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { TrackBase } from '../TrackBase';
|
|
6
|
-
import {
|
|
6
|
+
import { equalDeep, first, IntersectionRanges, logDebug, redispatchEvents, } from '@amazon/vinyl-util';
|
|
7
7
|
import { createContainer } from '@amazon/vinyl-di';
|
|
8
8
|
import { getMediaPeriodAtTime, } from '../../streaming/MediaTimeline';
|
|
9
9
|
/**
|
|
@@ -21,7 +21,6 @@ export class MseTrack extends TrackBase {
|
|
|
21
21
|
return this.deps.textTrackController ?? null;
|
|
22
22
|
}
|
|
23
23
|
streams = [];
|
|
24
|
-
disposeAbort = new Abort();
|
|
25
24
|
lastPreloadOptions = null;
|
|
26
25
|
allFetchedRanges = [];
|
|
27
26
|
_fetchedRanges = new IntersectionRanges(this.allFetchedRanges, { useCache: true });
|
|
@@ -48,7 +47,7 @@ export class MseTrack extends TrackBase {
|
|
|
48
47
|
if (this.active) {
|
|
49
48
|
this.deps.drmController.initializeForPlayback(event.current, {
|
|
50
49
|
trackUri: this.uri,
|
|
51
|
-
abort: this.
|
|
50
|
+
abort: this.drmSessionAbort.value,
|
|
52
51
|
});
|
|
53
52
|
}
|
|
54
53
|
});
|
|
@@ -61,7 +60,7 @@ export class MseTrack extends TrackBase {
|
|
|
61
60
|
return;
|
|
62
61
|
this.deps.drmController.setBufferingDrmInfo(event.current, {
|
|
63
62
|
trackUri: this.uri,
|
|
64
|
-
abort: this.
|
|
63
|
+
abort: this.drmSessionAbort.value,
|
|
65
64
|
});
|
|
66
65
|
});
|
|
67
66
|
// Listen for timeline changes to update qualities seek ranges and ads.
|
|
@@ -297,7 +296,7 @@ export class MseTrack extends TrackBase {
|
|
|
297
296
|
// AirPlay not supported using managed media sources
|
|
298
297
|
this.deps.playbackSource.disableRemotePlayback = true;
|
|
299
298
|
this.streams.forEach((stream) => {
|
|
300
|
-
this.deps.drmController.initializeForPlayback(stream.streamingQuality, { trackUri: this.uri, abort: this.
|
|
299
|
+
this.deps.drmController.initializeForPlayback(stream.streamingQuality, { trackUri: this.uri, abort: this.drmSessionAbort.value });
|
|
301
300
|
});
|
|
302
301
|
this.deps.playbackSource.src =
|
|
303
302
|
this.deps.mediaSourceController.activate();
|
|
@@ -327,7 +326,7 @@ export class MseTrack extends TrackBase {
|
|
|
327
326
|
// clear it here now that the track is no longer buffering.
|
|
328
327
|
this.deps.drmController.setBufferingDrmInfo(null, {
|
|
329
328
|
trackUri: this.uri,
|
|
330
|
-
abort: this.
|
|
329
|
+
abort: this.drmSessionAbort.value,
|
|
331
330
|
});
|
|
332
331
|
// Tear down the DOM text track so its cues stop showing while this
|
|
333
332
|
// track is suspended (e.g. an ad playing over it). The selection is
|