@dolby-optiview/ads-sdk-core 1.2.1 → 1.3.0
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/OptiViewAds.d.ts +5 -4
- package/dist/OptiViewAds.js +1 -1
- package/dist/external-playback/index.d.ts +4 -0
- package/dist/external-playback/index.js +1 -0
- package/dist/external-playback/observeExternalPlayback.d.ts +19 -0
- package/dist/external-playback/observeExternalPlayback.js +1 -0
- package/dist/external-playback/reconnectHold.d.ts +19 -0
- package/dist/external-playback/reconnectHold.js +1 -0
- package/dist/generated/diagnosticCodes.d.ts +45 -5
- package/dist/generated/diagnosticCodes.js +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +1 -1
- package/dist/interfaces/AdSourceQueue.d.ts +19 -0
- package/dist/interfaces/AdSourceQueue.js +1 -0
- package/dist/interfaces/PlayerAdapter.d.ts +31 -1
- package/dist/internal/index.d.ts +2 -0
- package/dist/internal/index.js +1 -1
- package/dist/services/AdBreakSequencer.d.ts +33 -4
- package/dist/services/AdBreakSequencer.js +1 -1
- package/dist/services/AdPlayerController.d.ts +8 -61
- package/dist/services/AdPlayerController.js +1 -1
- package/dist/services/BreakChain.d.ts +43 -0
- package/dist/services/BreakChain.js +1 -0
- package/dist/services/BreakChainRecorder.d.ts +63 -0
- package/dist/services/BreakChainRecorder.js +1 -0
- package/dist/services/BreakPreloadLedger.d.ts +13 -0
- package/dist/services/BreakPreloadLedger.js +1 -0
- package/dist/services/BreakScheduler.d.ts +20 -6
- package/dist/services/BreakScheduler.js +1 -1
- package/dist/services/BreakTransitionTimer.d.ts +27 -2
- package/dist/services/BreakTransitionTimer.js +1 -1
- package/dist/services/CmcdAdReporter.d.ts +1 -0
- package/dist/services/CmcdAdReporter.js +1 -1
- package/dist/services/ExternalPlaybackGate.d.ts +40 -0
- package/dist/services/ExternalPlaybackGate.js +1 -0
- package/dist/services/LiveStartPushbackController.d.ts +5 -10
- package/dist/services/LiveStartPushbackController.js +1 -1
- package/dist/services/ManifestService.d.ts +2 -1
- package/dist/services/ManifestService.js +1 -1
- package/dist/services/ReloadGuard.d.ts +11 -0
- package/dist/services/ReloadGuard.js +1 -0
- package/dist/services/RewindRearm.d.ts +3 -1
- package/dist/services/RewindRearm.js +1 -1
- package/dist/services/SsaiController.js +1 -1
- package/dist/services/adPlayer/AdPlayerCallbacks.d.ts +63 -0
- package/dist/services/adPlayer/AdPlayerCallbacks.js +1 -0
- package/dist/services/adPlayer/AdPlayerEvents.d.ts +2 -0
- package/dist/services/adPlayer/AdPlayerEvents.js +1 -1
- package/dist/services/adPlayer/AdPreloader.d.ts +2 -2
- package/dist/services/adPlayer/AdPreloader.js +1 -1
- package/dist/services/adPlayer/AdStage.d.ts +7 -4
- package/dist/services/adPlayer/AdStage.js +1 -1
- package/dist/services/adPlayer/AssetParameterResolver.d.ts +10 -2
- package/dist/services/adPlayer/AssetParameterResolver.js +1 -1
- package/dist/services/adPlayer/AssetPlayback.d.ts +6 -2
- package/dist/services/adPlayer/AssetPlayback.js +1 -1
- package/dist/services/adPlayer/BreakSequenceDriver.d.ts +9 -3
- package/dist/services/adPlayer/BreakSequenceDriver.js +1 -1
- package/dist/services/adPlayer/GamPodBridge.d.ts +11 -1
- package/dist/services/adPlayer/GamPodBridge.js +1 -1
- package/dist/services/adPlayer/PauseAdPresenter.d.ts +3 -1
- package/dist/services/adPlayer/PauseAdPresenter.js +1 -1
- package/dist/services/adPlayer/PreparedPresentation.js +1 -1
- package/dist/services/adPlayer/PresentationModeTracker.d.ts +1 -1
- package/dist/services/adPlayer/PresentationModeTracker.js +1 -1
- package/dist/services/adPlayer/SuccessorQueue.d.ts +36 -0
- package/dist/services/adPlayer/SuccessorQueue.js +1 -0
- package/dist/services/adPlayer/presentation/DomPresentationHost.d.ts +22 -0
- package/dist/services/adPlayer/presentation/DomPresentationHost.js +1 -0
- package/dist/services/adPlayer/presentation/LayoutTransform.d.ts +28 -0
- package/dist/services/adPlayer/presentation/LayoutTransform.js +1 -0
- package/dist/services/adPlayer/presentation/PresentationLayout.d.ts +19 -0
- package/dist/services/adPlayer/presentation/PresentationLayout.js +1 -0
- package/dist/services/assetParameterMacroTable.js +1 -1
- package/dist/services/assetParameterMacros.d.ts +9 -9
- package/dist/services/assetParameterMacros.js +1 -1
- package/dist/services/channelSwitch.d.ts +2 -2
- package/dist/services/externalPlaybackDiagnostic.d.ts +3 -0
- package/dist/services/externalPlaybackDiagnostic.js +1 -0
- package/dist/services/externalPlaybackGuard.d.ts +24 -0
- package/dist/services/externalPlaybackGuard.js +1 -0
- package/dist/services/parseBreakManifest.d.ts +2 -1
- package/dist/services/parseBreakManifest.js +1 -1
- package/dist/services/resolveChannelEvents.d.ts +17 -0
- package/dist/services/resolveChannelEvents.js +1 -0
- package/dist/services/resolveExternalVendorConfigurations.js +1 -1
- package/dist/services/resolveGamVendorConfiguration.d.ts +6 -1
- package/dist/services/resolveGamVendorConfiguration.js +1 -1
- package/dist/services/ssbStream.d.ts +39 -0
- package/dist/services/ssbStream.js +1 -0
- package/dist/services/ssbSwitchSignals.d.ts +15 -0
- package/dist/services/ssbSwitchSignals.js +1 -0
- package/dist/services/staticAssetUrl.d.ts +28 -0
- package/dist/services/staticAssetUrl.js +1 -0
- package/dist/session/AdBreakStatusTracker.d.ts +18 -0
- package/dist/session/AdBreakStatusTracker.js +1 -1
- package/dist/session/BreakLifecycle.d.ts +6 -0
- package/dist/session/BreakLifecycle.js +1 -1
- package/dist/session/SessionStarter.d.ts +6 -43
- package/dist/session/SessionStarter.js +1 -1
- package/dist/session/SessionStarterDeps.d.ts +39 -0
- package/dist/session/SessionStarterDeps.js +1 -0
- package/dist/session/SessionStarterHelpers.d.ts +36 -0
- package/dist/session/SessionStarterHelpers.js +1 -0
- package/dist/session/SessionState.d.ts +22 -2
- package/dist/session/SessionState.js +1 -1
- package/dist/session/SsbSwitch.d.ts +55 -0
- package/dist/session/SsbSwitch.js +1 -0
- package/dist/session/breakMeasurement.d.ts +16 -0
- package/dist/session/breakMeasurement.js +1 -0
- package/dist/session/contentSnapback.d.ts +13 -0
- package/dist/session/contentSnapback.js +1 -0
- package/dist/session/createExternalPlaybackGate.d.ts +19 -0
- package/dist/session/createExternalPlaybackGate.js +1 -0
- package/dist/session/sessionTick.d.ts +7 -0
- package/dist/session/sessionTick.js +1 -0
- package/dist/types/BreakManifest.d.ts +34 -2
- package/dist/types/Events.d.ts +20 -10
- package/dist/types/OptiViewAdsConfig.d.ts +24 -8
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{OptiViewAds}from"./OptiViewAds";export{OptiViewAdsExternalVendors}from"./OptiViewAdsExternalVendors";export{BreakFormat,AssetType,MediaType,Vendor,Timebase,DeviceType,Platform,Os,DeliveryMode,BreakEvent}from"./types/BreakManifest";export{isStaticAsset,isVastAsset,isVendorAsset,isGamVendorConfiguration,isEventTrigger,isPauseBreak}from"./types/BreakManifest";export{resolveDeliveryMode,resolveStitchedStreamVendor,SsaiUnavailableError}from"./services/resolveDeliveryMode";export{matchTargeting}from"./services/matchTargeting";export{DEFAULT_MODE,DEFAULT_AD_PRELOAD_MODE,DEFAULT_AD_BREAK_CONTENT_RECOVERY,DEFAULT_AD_INSERTION_MODE,DEFAULT_CHAINING,resolveChaining,DEFAULT_TUNE_IN,resolveTuneIn,DEFAULT_PDT_GRACE_SECONDS,resolvePdtGraceSeconds}from"./types/OptiViewAdsConfig";export{buildStitcherMasterUrl}from"./services/StitcherUrlBuilder";export{GamStreamManager}from"./services/GamStreamManager";export{OPTIVIEW_ASSET_PARAMETER_MACROS}from"./services/assetParameterMacros";export{VastAdManager,isImaCsaiSdkAvailable}from"./services/VastAdManager";export{SsaiController}from"./services/SsaiController";export{resolvePreloadMode,isSingleDecoderUserAgent}from"./services/detectPreloadMode";export{detectDeviceProfile}from"./services/detectDeviceType";export{resolveContentRecovery,isRecreateAfterBreakUserAgent}from"./services/detectContentRecovery";export{resolveInsertionMode,isSharedElementUserAgent,detectMediaSourceCapabilities}from"./services/detectInsertionMode";export{systemClock}from"./services/BreakScheduler";export{MetadataCueTracker,isAnvatoCue,isId3InEmsgScheme,anvatoPayloadFromCue,parseAnvatoPayload,ANVATO_ID3_DESCRIPTION,ANVATO_ID3_MIME_TYPE,ANVATO_EMSG_SCHEME_ID_URI,ID3_IN_EMSG_SCHEME_ID_URIS,PTS_MATCH_TOLERANCE_SECONDS}from"./services/MetadataCueTracker";export{PauseAdController}from"./services/PauseAdController";export{parseVastCompanionImage}from"./services/parseVastCompanion";export{AdBreakSequencer,selectVariant,extractAssets,assetsOfVariant,resolveBreakFormat,breakPlanEmptyReason}from"./services/AdBreakSequencer";export{selectVariantDetailed,playableFormatsFor,variantsOf,RENDERABLE_BREAK_FORMATS,KNOWN_BREAK_FORMATS}from"./services/selectVariant";export{GamPodAdTracker,derivePodAdAsset}from"./services/GamPodAdTracker";export{DIAGNOSTIC_CODES,getDiagnosticCodeInfo,DiagnosticBuffer,DEFAULT_DIAGNOSTIC_BUFFER_SIZE,SDK_VERSION}from"./diagnostics";export{parseBreakManifest,SUPPORTED_MANIFEST_MAJOR_VERSION}from"./services/parseBreakManifest";export{fetchWithTimeout,AUX_FETCH_TIMEOUT_MS}from"./services/fetchWithTimeout";export{buildGamPodUrl,isGamVendorParameters}from"./services/GamPodUrlBuilder";
|
|
1
|
+
export{OptiViewAds}from"./OptiViewAds";export{OptiViewAdsExternalVendors}from"./OptiViewAdsExternalVendors";export{BreakFormat,AssetType,MediaType,Vendor,Timebase,DeviceType,Platform,Os,DeliveryMode,BreakEvent}from"./types/BreakManifest";export{isStaticAsset,isVastAsset,isVendorAsset,isGamVendorConfiguration,isEventTrigger,isPauseBreak}from"./types/BreakManifest";export{resolveDeliveryMode,resolveStitchedStreamVendor,SsaiUnavailableError}from"./services/resolveDeliveryMode";export{matchTargeting}from"./services/matchTargeting";export{DEFAULT_MODE,DEFAULT_AD_PRELOAD_MODE,DEFAULT_AD_BREAK_CONTENT_RECOVERY,DEFAULT_AD_INSERTION_MODE,DEFAULT_CHAINING,resolveChaining,DEFAULT_TUNE_IN,resolveTuneIn,DEFAULT_PDT_GRACE_SECONDS,resolvePdtGraceSeconds}from"./types/OptiViewAdsConfig";export{buildStitcherMasterUrl}from"./services/StitcherUrlBuilder";export{GamStreamManager}from"./services/GamStreamManager";export{OPTIVIEW_ASSET_PARAMETER_MACROS}from"./services/assetParameterMacros";export{VastAdManager,isImaCsaiSdkAvailable}from"./services/VastAdManager";export{SsaiController}from"./services/SsaiController";export{resolvePreloadMode,isSingleDecoderUserAgent}from"./services/detectPreloadMode";export{detectDeviceProfile}from"./services/detectDeviceType";export{resolveContentRecovery,isRecreateAfterBreakUserAgent}from"./services/detectContentRecovery";export{resolveInsertionMode,isSharedElementUserAgent,detectMediaSourceCapabilities}from"./services/detectInsertionMode";export{systemClock}from"./services/BreakScheduler";export{MetadataCueTracker,isAnvatoCue,isId3InEmsgScheme,anvatoPayloadFromCue,parseAnvatoPayload,ANVATO_ID3_DESCRIPTION,ANVATO_ID3_MIME_TYPE,ANVATO_EMSG_SCHEME_ID_URI,ID3_IN_EMSG_SCHEME_ID_URIS,PTS_MATCH_TOLERANCE_SECONDS}from"./services/MetadataCueTracker";export{PauseAdController}from"./services/PauseAdController";export{parseVastCompanionImage}from"./services/parseVastCompanion";export{AdBreakSequencer,selectVariant,extractAssets,assetsOfVariant,resolveBreakFormat,breakPlanEmptyReason}from"./services/AdBreakSequencer";export{selectVariantDetailed,playableFormatsFor,variantsOf,RENDERABLE_BREAK_FORMATS,KNOWN_BREAK_FORMATS}from"./services/selectVariant";export{GamPodAdTracker,derivePodAdAsset}from"./services/GamPodAdTracker";export{DIAGNOSTIC_CODES,getDiagnosticCodeInfo,DiagnosticBuffer,DEFAULT_DIAGNOSTIC_BUFFER_SIZE,SDK_VERSION}from"./diagnostics";export{parseBreakManifest,SUPPORTED_MANIFEST_MAJOR_VERSION}from"./services/parseBreakManifest";export{resolveActiveEvent,resolveEventManifest,nextEventBoundaryMs}from"./services/resolveChannelEvents";export{fetchWithTimeout,AUX_FETCH_TIMEOUT_MS}from"./services/fetchWithTimeout";export{buildGamPodUrl,isGamVendorParameters}from"./services/GamPodUrlBuilder";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PlayerAdapter } from './PlayerAdapter';
|
|
2
|
+
/**
|
|
3
|
+
* Optional capability of the SDK's own web ad player: buffer the next ad behind the playing one,
|
|
4
|
+
* so a back-to-back break starts without a reload. Internal; no compatibility promise.
|
|
5
|
+
*/
|
|
6
|
+
export interface AdSourceQueue {
|
|
7
|
+
/**
|
|
8
|
+
* Buffers `url` behind the playing ad. Resolves `true` once it is appended behind it, `false` when
|
|
9
|
+
* that is not possible (the caller keeps the cold path). `onLost` fires at most once when an
|
|
10
|
+
* accepted source can no longer be used; never after {@link takeQueued} or {@link clearQueued}.
|
|
11
|
+
*/
|
|
12
|
+
queueNext(url: string, onLost: () => void): Promise<boolean>;
|
|
13
|
+
/** Makes the queued `url` the current source without `load()`; `false` when it is not queued. */
|
|
14
|
+
takeQueued(url: string): boolean;
|
|
15
|
+
/** Drops the queued source; media appended behind the playing ad never reaches the screen. */
|
|
16
|
+
clearQueued(): void;
|
|
17
|
+
}
|
|
18
|
+
/** Whether `player` can queue the next ad behind the playing one. */
|
|
19
|
+
export declare function hasAdSourceQueue(player: PlayerAdapter | null | undefined): player is PlayerAdapter & AdSourceQueue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function hasAdSourceQueue(e){const u=e;return"function"==typeof u?.queueNext&&"function"==typeof u.takeQueued&&"function"==typeof u.clearQueued}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Events a PlayerAdapter must support. `timedmetadata` is capability-style: adapters that
|
|
3
3
|
* can surface in-stream markers (HLS ID3 / EXT-X-DATERANGE, DASH emsg) emit it per marker.
|
|
4
|
+
* `externalplaybackchange` is capability-style too: adapters that can detect AirPlay emit an
|
|
5
|
+
* {@link ExternalPlaybackChange} whenever the content player's external playback state changes.
|
|
4
6
|
* @category Player Integration */
|
|
5
|
-
export type PlayerAdapterEvent = 'timeupdate' | 'ended' | 'error' | 'seeked' | 'volumechange' | 'waiting' | 'playing' | 'pause' | 'timedmetadata';
|
|
7
|
+
export type PlayerAdapterEvent = 'timeupdate' | 'ended' | 'error' | 'seeked' | 'volumechange' | 'waiting' | 'playing' | 'pause' | 'timedmetadata' | 'externalplaybackchange';
|
|
8
|
+
/**
|
|
9
|
+
* External (AirPlay) playback state of the content player. `connecting` is a hint: the route moved
|
|
10
|
+
* to an AirPlay output, but video may or may not follow (screen mirroring and audio-only targets
|
|
11
|
+
* look the same). `active` is authoritative: the receiver renders the video. `inactive` follows either.
|
|
12
|
+
* On iOS, a closed gate while the route stays on AirPlay reads `connecting`.
|
|
13
|
+
* @category Player Integration */
|
|
14
|
+
export type ExternalPlaybackState = 'connecting' | 'active' | 'inactive';
|
|
15
|
+
/** What the external playback target is, when the platform tells. @category Player Integration */
|
|
16
|
+
export type ExternalPlaybackTarget = 'airplay' | 'unknown';
|
|
17
|
+
/** Payload of `externalplaybackchange`. @category Player Integration */
|
|
18
|
+
export interface ExternalPlaybackChange {
|
|
19
|
+
/** The new state. */
|
|
20
|
+
state: ExternalPlaybackState;
|
|
21
|
+
/** The kind of target the content is routed to. */
|
|
22
|
+
target: ExternalPlaybackTarget;
|
|
23
|
+
}
|
|
6
24
|
/**
|
|
7
25
|
* One in-stream timed-metadata marker (payload of `timedmetadata`). Minimal, player-agnostic:
|
|
8
26
|
* - `id3`: HLS ID3 — parsed text `frames` and/or undecoded `raw` bytes.
|
|
@@ -207,6 +225,18 @@ export interface PlayerAdapter {
|
|
|
207
225
|
* passing `null` restores the exact prior selection.
|
|
208
226
|
*/
|
|
209
227
|
setVideoQuality?(quality: VideoQuality | null): boolean;
|
|
228
|
+
/**
|
|
229
|
+
* Current external (AirPlay) playback state of the content player; `undefined` when the adapter
|
|
230
|
+
* cannot detect it. Changes are announced with the `externalplaybackchange` event.
|
|
231
|
+
*/
|
|
232
|
+
readonly externalPlaybackState?: ExternalPlaybackState | undefined;
|
|
233
|
+
/**
|
|
234
|
+
* Allow or block external VIDEO playback (AirPlay). The SDK calls it on the content player
|
|
235
|
+
* while a server-side beaconing stream is available, and with `false` once on every separate
|
|
236
|
+
* ad adapter from `createAdAdapter(container)` right after `prepareForAdPlayback`, so an ad
|
|
237
|
+
* can never take the content's AirPlay route. Omit when unsupported.
|
|
238
|
+
*/
|
|
239
|
+
setExternalPlaybackAllowed?(allowed: boolean): void;
|
|
210
240
|
/** Clean up resources when the SDK is destroyed. */
|
|
211
241
|
destroy(): void;
|
|
212
242
|
}
|
package/dist/internal/index.d.ts
CHANGED
package/dist/internal/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{preparePresentation,getPreparedPresentation,disposePreparedPresentation}from"../services/adPlayer/PreparedPresentation";
|
|
1
|
+
export{preparePresentation,getPreparedPresentation,disposePreparedPresentation}from"../services/adPlayer/PreparedPresentation";export{hasAdSourceQueue}from"../interfaces/AdSourceQueue";
|
|
@@ -7,7 +7,8 @@ import { type VariantSelectionInputs } from './selectVariant';
|
|
|
7
7
|
* outcomes, so the event contract has one source of truth across platforms (`conformance/`).
|
|
8
8
|
* - `lshape_content` shows a backdrop with no ad video: only `adbreakbegin`/`adbreakend`.
|
|
9
9
|
* - Shared-element plays only the first asset as a single fullscreen ad; `lshape_content` is skipped.
|
|
10
|
-
* - Chaining
|
|
10
|
+
* - Chaining: the finished break `adbreakend`s and the successor `adbreakbegin`s at once. While the
|
|
11
|
+
* last ad plays, `prepare-successor` names the successor's first ad so a renderer can buffer it.
|
|
11
12
|
*/
|
|
12
13
|
/** The insertion mode the sequencer needs, after `adaptive` has been resolved. */
|
|
13
14
|
export type EffectiveInsertionMode = 'overlay' | 'shared-element';
|
|
@@ -39,13 +40,27 @@ export type AdBreakAction =
|
|
|
39
40
|
| {
|
|
40
41
|
kind: 'render-backdrop';
|
|
41
42
|
}
|
|
42
|
-
/** The break has fully ended (no chain): tear down
|
|
43
|
+
/** The break has fully ended (no chain): tear down, discard any prepared successor, resume content. */
|
|
43
44
|
| {
|
|
44
45
|
kind: 'end-break';
|
|
45
46
|
}
|
|
46
47
|
/** Nothing to do; the driver awaits the next outcome (asset end/error/timer). */
|
|
47
48
|
| {
|
|
48
49
|
kind: 'await';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* While the break's last ad plays: buffer `asset`, the first ad the chain plays next (of
|
|
53
|
+
* `break`), behind it. Replaces any successor prepared before. A driver may ignore it.
|
|
54
|
+
*/
|
|
55
|
+
| {
|
|
56
|
+
kind: 'prepare-successor';
|
|
57
|
+
break: Break;
|
|
58
|
+
asset: Asset;
|
|
59
|
+
}
|
|
60
|
+
/** The prepared successor `breakId` will not play next: discard it. */
|
|
61
|
+
| {
|
|
62
|
+
kind: 'drop-successor';
|
|
63
|
+
breakId: string;
|
|
49
64
|
};
|
|
50
65
|
/** An outcome the driver reports back to advance the sequence. */
|
|
51
66
|
export type AdBreakOutcome =
|
|
@@ -68,6 +83,10 @@ export type AdBreakOutcome =
|
|
|
68
83
|
/** The break's max-duration timer elapsed, cutting the break short. */
|
|
69
84
|
| {
|
|
70
85
|
kind: 'break-elapsed';
|
|
86
|
+
}
|
|
87
|
+
/** The chained successor of the current break appeared, changed or disappeared. */
|
|
88
|
+
| {
|
|
89
|
+
kind: 'successor-changed';
|
|
71
90
|
};
|
|
72
91
|
/**
|
|
73
92
|
* Why a break produced no ad: `no-variant`, `no-qualifying-variant` (none passed device
|
|
@@ -118,12 +137,14 @@ export declare class AdBreakSequencer {
|
|
|
118
137
|
private readonly insertionMode;
|
|
119
138
|
private readonly chainResolver;
|
|
120
139
|
private readonly selection;
|
|
140
|
+
private readonly successorResolver;
|
|
121
141
|
private currentBreak;
|
|
122
142
|
private plan;
|
|
123
143
|
private assetIndex;
|
|
124
144
|
/** True once the current asset emitted `adbegin` and has not yet settled. */
|
|
125
145
|
private assetStarted;
|
|
126
|
-
|
|
146
|
+
/** Break id named by the last `prepare-successor` of the current break, until it is dropped or the break ends. */
|
|
147
|
+
private preparedSuccessorId;
|
|
127
148
|
/** The SELECTED (or downgrade-candidate) variant's format, not the first declared variant's. */
|
|
128
149
|
private planFormat;
|
|
129
150
|
/** Emits `adbreakbegin` and returns the first action; a break with nothing to play is retired without beginning. */
|
|
@@ -136,11 +157,19 @@ export declare class AdBreakSequencer {
|
|
|
136
157
|
private startAction;
|
|
137
158
|
/** Advance the sequence with a driver outcome. */
|
|
138
159
|
onOutcome(outcome: AdBreakOutcome): AdBreakTransition;
|
|
160
|
+
/**
|
|
161
|
+
* Only while the break's last ad plays: an earlier queued item would play before the break's
|
|
162
|
+
* own next ad. Drops a prepared successor that the chain no longer plays next.
|
|
163
|
+
*/
|
|
164
|
+
private successorAction;
|
|
165
|
+
private playingLastAsset;
|
|
166
|
+
/** The first ad the chain plays after `breakInfo`; successors with nothing to play are passed over, as the advance does. */
|
|
167
|
+
private firstSuccessorAd;
|
|
139
168
|
/** The `adend` owed to an ad that began but has not settled, when a break is cut short. */
|
|
140
169
|
private inFlightAdendPrefix;
|
|
141
170
|
private onAssetStarted;
|
|
142
171
|
/** A failure emits `aderror` then `adend` regardless; then advance or finalize. */
|
|
143
172
|
private onAssetSettled;
|
|
144
|
-
/** Emit `adbreakend`;
|
|
173
|
+
/** Emit `adbreakend`; a chained successor `adbreakbegin`s at once through the held ad surface. */
|
|
145
174
|
private finalizeBreak;
|
|
146
175
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BreakFormat as
|
|
1
|
+
import{BreakFormat as e}from"../types/BreakManifest";import{KNOWN_BREAK_FORMATS as t,selectVariantDetailed as s,variantsOf as a}from"./selectVariant";export function selectVariant(e,a){return s(e,a??{playableFormats:t}).selected}export function resolveBreakFormat(e,t){return selectVariant(e,t)?.format}export function assetsOfVariant(t){if(!t)return[];switch(t.format){case e.SINGLE:case e.DOUBLE:case e.LSHAPE_AD:case e.LSHAPE_CONTENT:case e.OVERLAY:return t.assets;default:return[]}}export function extractAssets(e,t){return assetsOfVariant(selectVariant(e,t))}export function breakPlanEmptyReason(e,t,s={}){const a=r(e,t,s);return"empty"===a.mode?a.reason??null:null}function r(r,n,i={}){if(0===a(r).length)return{mode:"empty",reason:"no-variant",variant:null};const o=s(r,{deviceType:i.deviceType,deviceProfile:i.deviceProfile,playableFormats:"shared-element"===n?t:i.playableFormats}),d=o.selected,l=d??o.deviceQualified;if(!l)return{mode:"empty",reason:"no-qualifying-variant",variant:null};if("shared-element"===n){if(l.format===e.LSHAPE_CONTENT)return{mode:"empty",reason:"lshape-content-skipped",variant:l};const t=assetsOfVariant(l)[0];return t?{mode:"shared-single",asset:t,variant:l}:{mode:"empty",reason:"no-assets",variant:l}}if(d){if(d.format===e.LSHAPE_CONTENT)return{mode:"overlay-backdrop",variant:d};const t=assetsOfVariant(d);return t.length>0?{mode:"overlay-assets",assets:t,variant:d}:{mode:"empty",reason:"no-assets",variant:d}}if(l.format===e.LSHAPE_CONTENT)return{mode:"overlay-backdrop",variant:l};const h=assetsOfVariant(l)[0];return h?{mode:"overlay-assets",assets:[h],variant:l}:{mode:"empty",reason:"no-assets",variant:l}}export class AdBreakSequencer{constructor(e,t=()=>null,s={},a=t){this.insertionMode=e,this.chainResolver=t,this.selection=s,this.successorResolver=a,this.currentBreak=null,this.plan={mode:"empty"},this.assetIndex=0,this.assetStarted=!1,this.preparedSuccessorId=null}planFormat(){return"variant"in this.plan?this.plan.variant?.format:void 0}beginBreak(e){if(this.currentBreak=e,this.plan=r(e,this.insertionMode,this.selection),this.assetIndex=0,this.assetStarted=!1,this.preparedSuccessorId=null,"empty"===this.plan.mode)return this.retireEmptyBreak(e,[],this.noticeFor(e));return{steps:[{type:"adbreakbegin",break:e,format:this.planFormat()}],action:this.startAction(this.plan)}}noticeFor(e){return"empty"===this.plan.mode&&this.plan.reason?[{breakId:e.id,reason:this.plan.reason,format:this.plan.variant?.format,declaredAssetCount:a(e).reduce((e,t)=>e+assetsOfVariant(t).length,0)}]:[]}retireEmptyBreak(e,t,s){const a=[...t,{type:"aderror",break:e,format:this.planFormat()}],n=this.chainResolver(e.id);return n?(this.currentBreak=n,this.plan=r(n,this.insertionMode,this.selection),this.assetIndex=0,this.assetStarted=!1,this.preparedSuccessorId=null,"empty"===this.plan.mode?this.retireEmptyBreak(n,a,[...s,...this.noticeFor(n)]):(a.push({type:"adbreakbegin",break:n,format:this.planFormat()}),{steps:a,action:this.startAction(this.plan),noPlayableAsset:s})):(this.currentBreak=null,{steps:a,action:{kind:"end-break"},noPlayableAsset:s})}startAction(e){switch(e.mode){case"overlay-assets":return{kind:"play-asset",asset:e.assets[0],index:0,total:e.assets.length};case"overlay-backdrop":return{kind:"render-backdrop"};case"shared-single":return{kind:"play-shared",asset:e.asset}}}onOutcome(e){if(!this.currentBreak)return{steps:[],action:{kind:"await"}};const t=this.currentBreak;switch(e.kind){case"asset-started":return this.onAssetStarted(t);case"asset-ended":return this.onAssetSettled(t,!1);case"asset-errored":return this.onAssetSettled(t,!0);case"backdrop-elapsed":case"break-elapsed":return this.finalizeBreak(this.inFlightAdendPrefix(t));case"successor-changed":return{steps:[],action:this.successorAction(t)}}}successorAction(e){if(!this.playingLastAsset())return{kind:"await"};const t=this.firstSuccessorAd(e);if(t)return this.preparedSuccessorId=t.break.id,{kind:"prepare-successor",break:t.break,asset:t.asset};const s=this.preparedSuccessorId;return null===s?{kind:"await"}:(this.preparedSuccessorId=null,{kind:"drop-successor",breakId:s})}upcomingAsset(){return this.currentBreak&&"overlay-assets"===this.plan.mode?this.plan.assets[this.assetIndex+1]??null:null}playingLastAsset(){return!!this.assetStarted&&("shared-single"===this.plan.mode||"overlay-assets"===this.plan.mode&&this.assetIndex===this.plan.assets.length-1)}firstSuccessorAd(e){const t=new Set([e.id]);let s=this.successorResolver(e.id);for(;s&&!t.has(s.id);){t.add(s.id);const e=r(s,this.insertionMode,this.selection);if("overlay-assets"===e.mode)return{break:s,asset:e.assets[0]};if("shared-single"===e.mode)return{break:s,asset:e.asset};if("empty"!==e.mode)return null;s=this.successorResolver(s.id)}return null}inFlightAdendPrefix(e){if(!this.assetStarted)return[];const t=this.planFormat();return"overlay-assets"===this.plan.mode?[{type:"adend",break:e,format:t,asset:this.plan.assets[this.assetIndex],adIndex:this.assetIndex,totalAds:this.plan.assets.length}]:"shared-single"===this.plan.mode?[{type:"adend",break:e,format:t,asset:this.plan.asset,adIndex:0,totalAds:1}]:[]}onAssetStarted(e){if("overlay-assets"===this.plan.mode){const t=this.plan.assets.length,s=this.plan.assets[this.assetIndex];return this.assetStarted=!0,{steps:[{type:"adbegin",break:e,format:this.planFormat(),asset:s,adIndex:this.assetIndex,totalAds:t}],action:this.successorAction(e)}}return"shared-single"===this.plan.mode?(this.assetStarted=!0,{steps:[{type:"adbegin",break:e,format:this.planFormat(),asset:this.plan.asset,adIndex:0,totalAds:1}],action:this.successorAction(e)}):{steps:[],action:{kind:"await"}}}onAssetSettled(e,t){if(this.assetStarted=!1,"shared-single"===this.plan.mode){const s=[],a=this.plan.asset,r=this.planFormat();return t&&s.push({type:"aderror",break:e,format:r,asset:a,adIndex:0,totalAds:1}),s.push({type:"adend",break:e,format:r,asset:a,adIndex:0,totalAds:1}),this.finalizeBreak(s)}if("overlay-assets"!==this.plan.mode)return{steps:[],action:{kind:"await"}};const s=this.plan.assets.length,a=this.plan.assets[this.assetIndex],r=[],n=this.planFormat();return t&&r.push({type:"aderror",break:e,format:n,asset:a,adIndex:this.assetIndex,totalAds:s}),r.push({type:"adend",break:e,format:n,asset:a,adIndex:this.assetIndex,totalAds:s}),this.assetIndex+=1,this.assetIndex<s?{steps:r,action:{kind:"play-asset",asset:this.plan.assets[this.assetIndex],index:this.assetIndex,total:s}}:this.finalizeBreak(r)}finalizeBreak(e,t=[]){const s=e=>t.length>0?{...e,noPlayableAsset:t}:e,a=this.currentBreak;if(!a)return s({steps:e,action:{kind:"end-break"}});const n=[...e,{type:"adbreakend",break:a,format:this.planFormat()}];this.preparedSuccessorId=null;const i=this.chainResolver(a.id);return i?(this.currentBreak=i,this.plan=r(i,this.insertionMode,this.selection),this.assetIndex=0,this.assetStarted=!1,"empty"===this.plan.mode?this.retireEmptyBreak(i,n,[...t,...this.noticeFor(i)]):(n.push({type:"adbreakbegin",break:i,format:this.planFormat()}),s({steps:n,action:this.startAction(this.plan)}))):(this.currentBreak=null,s({steps:n,action:{kind:"end-break"}}))}}
|
|
@@ -12,62 +12,10 @@ import type { PauseAdResolution } from './PauseAdController';
|
|
|
12
12
|
import { type Clock } from './BreakScheduler';
|
|
13
13
|
import { PauseAdPresenter } from './adPlayer/PauseAdPresenter';
|
|
14
14
|
import { AssetParameterResolver } from './adPlayer/AssetParameterResolver';
|
|
15
|
+
import { GamPodBridge } from './adPlayer/GamPodBridge';
|
|
15
16
|
import type { BreakEndOnStreamClock } from './adPlayer/streamClockResume';
|
|
16
|
-
|
|
17
|
-
export
|
|
18
|
-
adId?: string | undefined;
|
|
19
|
-
creativeId?: string | undefined;
|
|
20
|
-
/** 1-based position within the pod (IMA `getAdPodInfo().getAdPosition()` / VAST `sequence`); absent when unreported. */
|
|
21
|
-
podPosition?: number | undefined;
|
|
22
|
-
}
|
|
23
|
-
export interface AdPlayerCallbacks {
|
|
24
|
-
onAdStart: (breakInfo: Break, asset: Asset, index: number, total: number, identity?: AdCreativeIdentity) => void;
|
|
25
|
-
onAdEnd: (breakInfo: Break, asset: Asset, index: number, total: number, identity?: AdCreativeIdentity) => void;
|
|
26
|
-
/** `asset` is undefined for a break-level error (no playable variant, the break never began). */
|
|
27
|
-
onAdError: (breakInfo: Break, asset: Asset | undefined, error: Error) => void;
|
|
28
|
-
onAdTimeUpdate: (breakInfo: Break, asset: Asset, currentTime: number, duration: number) => void;
|
|
29
|
-
onAdWaiting: (breakInfo: Break, asset: Asset) => void;
|
|
30
|
-
onAdPlaying: (breakInfo: Break, asset: Asset) => void;
|
|
31
|
-
onBreakEnd: (breakInfo: Break) => void;
|
|
32
|
-
/** The break-cut timer expired with an ad still in flight; fired before that ad's `adend`. */
|
|
33
|
-
onBreakCut?: (breakInfo: Break) => void;
|
|
34
|
-
/**
|
|
35
|
-
* A content-covering break ended before its content pause landed, so no player transition
|
|
36
|
-
* announces the resume. Only the deferred-pause renderers (Kotlin/Swift) fire this.
|
|
37
|
-
*/
|
|
38
|
-
onBreakEndedWithoutContentPause?: (breakInfo: Break) => void;
|
|
39
|
-
/** Ad overlay became visible; gates `adbreakbegin` so the AD badge never precedes the first ad frame. */
|
|
40
|
-
onBreakVisible?: (breakInfo: Break) => void;
|
|
41
|
-
/** The current break soft-ended into a chained successor (overlay held, no content resume). */
|
|
42
|
-
onChainedBreakBegin?: (next: Break) => void;
|
|
43
|
-
/** A chained successor resolved but has nothing to play; the SDK must retire it (completeBreak). */
|
|
44
|
-
onChainedBreakSkipped?: (next: Break) => void;
|
|
45
|
-
/**
|
|
46
|
-
* Fired just before the runtime's own post-break resume-seek, so the scheduler does not read
|
|
47
|
-
* the backward step as a DVR seek-back and re-arm the break.
|
|
48
|
-
*/
|
|
49
|
-
onContentResumeSeek?: (targetSeconds: number, breakEndSeconds: number) => void;
|
|
50
|
-
/**
|
|
51
|
-
* Brackets a content RELOAD (shared-element break end), so the playhead passing through the
|
|
52
|
-
* start of the freshly loaded stream is not read as a seek back before the break.
|
|
53
|
-
*/
|
|
54
|
-
onContentReloading?: (active: boolean) => void;
|
|
55
|
-
}
|
|
56
|
-
export interface PlayBreakOptions {
|
|
57
|
-
/** Seconds to present the break for (tune-in breaks: the remaining time); defaults to `break.duration`. */
|
|
58
|
-
effectiveDurationSec?: number;
|
|
59
|
-
/** Defer the overlay and `onBreakVisible` until the first ad frame renders (held delay:0 fullscreen pre-rolls). */
|
|
60
|
-
firstFrameGate?: boolean;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* IMA quartile callbacks. `adIndex`/`totalAds` attribute the milestone to one ad of a
|
|
64
|
-
* multi-ad GAM pod; omitted when there is no per-ad breakdown.
|
|
65
|
-
*/
|
|
66
|
-
export interface GamEventCallbacks {
|
|
67
|
-
onAdFirstQuartile?: (breakInfo: Break, asset: Asset, adIndex?: number, totalAds?: number) => void;
|
|
68
|
-
onAdMidpoint?: (breakInfo: Break, asset: Asset, adIndex?: number, totalAds?: number) => void;
|
|
69
|
-
onAdThirdQuartile?: (breakInfo: Break, asset: Asset, adIndex?: number, totalAds?: number) => void;
|
|
70
|
-
}
|
|
17
|
+
import type { AdCreativeIdentity, AdPlayerCallbacks, GamEventCallbacks, PlayBreakOptions } from './adPlayer/AdPlayerCallbacks';
|
|
18
|
+
export type { AdCreativeIdentity, AdPlayerCallbacks, GamEventCallbacks, PlayBreakOptions };
|
|
71
19
|
export declare class AdPlayerController {
|
|
72
20
|
private static readonly AD_START_BUDGET_MS;
|
|
73
21
|
private static readonly GAM_POD_AD_START_BUDGET_MS;
|
|
@@ -99,12 +47,13 @@ export declare class AdPlayerController {
|
|
|
99
47
|
private readonly state;
|
|
100
48
|
readonly pauseAdPresenter: PauseAdPresenter;
|
|
101
49
|
private readonly assetParameters;
|
|
102
|
-
|
|
50
|
+
readonly gamPodBridge: GamPodBridge;
|
|
103
51
|
private readonly adStage;
|
|
104
52
|
private destroyed;
|
|
105
53
|
private readonly preloader;
|
|
106
54
|
private readonly assetPlayback;
|
|
107
55
|
private readonly breakSequenceDriver;
|
|
56
|
+
private readonly successorQueue;
|
|
108
57
|
private readonly variantSelector;
|
|
109
58
|
private readonly adPlayerEvents;
|
|
110
59
|
private get gamEventCallbacks();
|
|
@@ -235,6 +184,8 @@ export declare class AdPlayerController {
|
|
|
235
184
|
private clearContentGate;
|
|
236
185
|
/** `null` disables chaining: breaks then always hard-end regardless of how close the next one is. */
|
|
237
186
|
setChainResolver(resolver: ((currentBreakId: string) => Break | null) | null): void;
|
|
187
|
+
/** The playing break's chained successor appeared, changed or disappeared: re-queue or drop its first ad. */
|
|
188
|
+
onChainSuccessorChanged(): void;
|
|
238
189
|
/** {@link ContentResumeCoordinator.setCueAnchorResolver}. */
|
|
239
190
|
setResumeCueAnchorResolver(resolver: ((breakInfo: Break) => number | null) | null): void;
|
|
240
191
|
/** {@link ContentResumeCoordinator.setCueEndResolver}. */
|
|
@@ -279,6 +230,7 @@ export declare class AdPlayerController {
|
|
|
279
230
|
setSessionAssetParameterMacros(macros: AssetParameterMacros | undefined): void;
|
|
280
231
|
get sessionAssetParameterMacros(): AssetParameterMacros;
|
|
281
232
|
private buildVastTagUrl;
|
|
233
|
+
private buildStaticAssetUrl;
|
|
282
234
|
private pushAssetParameters;
|
|
283
235
|
private setupOverlay;
|
|
284
236
|
/** Always creates a fresh IMA session. */
|
|
@@ -413,11 +365,6 @@ export declare class AdPlayerController {
|
|
|
413
365
|
declaredFormatOf(breakInfo: Break): BreakFormat | undefined;
|
|
414
366
|
private getVariant;
|
|
415
367
|
private applyLayout;
|
|
416
|
-
/**
|
|
417
|
-
* For double/lshape_ad/lshape_content, playerContainer keeps its break-time z-index (101)
|
|
418
|
-
* during the transition so it stays above the still-fading adContainer (z:100) and companion
|
|
419
|
-
* (z:99); otherwise the backdrop cuts to black instead of content growing back.
|
|
420
|
-
*/
|
|
421
368
|
private restoreLayout;
|
|
422
369
|
/**
|
|
423
370
|
* Selection-aware: without the inputs, a device-targeted variant's assets would read as empty
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BreakFormat as e,Timebase as t,isPostRollBreak as r}from"../types/BreakManifest";import{DEFAULT_AD_BREAK_CUT_SAFETY_MARGIN_SEC as s,DEFAULT_DOUBLE_BOX_AUDIO as a}from"../types/OptiViewAdsConfig";import{pipOverridesFormat as i,pipSuppressesBackdrop as n}from"./pictureInPicture";import{AdBreakSequencer as o,assetsOfVariant as d,resolveBreakFormat as l}from"./AdBreakSequencer";import{selectVariantDetailed as h}from"./selectVariant";import{debugLog as u}from"../diagnostics/debugLog";import{systemClock as c}from"./BreakScheduler";import{createAdPlayerState as m,invalidateMediaPreload as g}from"./adPlayer/AdPlayerState";import{PauseAdPresenter as P}from"./adPlayer/PauseAdPresenter";import{AssetParameterResolver as y}from"./adPlayer/AssetParameterResolver";import{GamPodBridge as p}from"./adPlayer/GamPodBridge";import{AdStage as A}from"./adPlayer/AdStage";import{AdPreloader as v}from"./adPlayer/AdPreloader";import{PresentationModeTracker as C}from"./adPlayer/PresentationModeTracker";import{SharedElementBreakPlayer as k}from"./adPlayer/SharedElementBreakPlayer";import{ContentResumeCoordinator as f}from"./adPlayer/ContentResumeCoordinator";import{resumeContentAfterBreak as S}from"./adPlayer/ContentRecovery";import{AssetPlayback as B}from"./adPlayer/AssetPlayback";import{BreakSequenceDriver as E}from"./adPlayer/BreakSequenceDriver";import{VariantSelector as b}from"./adPlayer/VariantSelector";import{AdPlayerEvents as F}from"./adPlayer/AdPlayerEvents";import{armPlaybackCutoff as T,clearPlaybackCutoff as M}from"./adPlayer/PlaybackCutoff";import{AdError as R}from"../types/AdError";export class AdPlayerController{get contentPaused(){return this.state.contentPaused}set contentPaused(e){this.state.contentPaused=e}get firstFrameGateActive(){return this.state.firstFrameGateActive}set firstFrameGateActive(e){this.state.firstFrameGateActive=e}get firstFrameGateShown(){return this.state.firstFrameGateShown}set firstFrameGateShown(e){this.state.firstFrameGateShown=e}get firstFrameRejector(){return this.state.firstFrameRejector}set firstFrameRejector(e){this.state.firstFrameRejector=e}get gamEventCallbacks(){return this.gamPodBridge.eventCallbacks}get vastAdManager(){return this.state.vastAdManager}set vastAdManager(e){this.state.vastAdManager=e}get currentBreak(){return this.state.currentBreak}set currentBreak(e){this.state.currentBreak=e}get currentAsset(){return this.state.currentAsset}set currentAsset(e){this.state.currentAsset=e}get callbacks(){return this.state.callbacks}set callbacks(e){this.state.callbacks=e}get isPlaying(){return this.state.isPlaying}set isPlaying(e){this.state.isPlaying=e}get effectiveBreakDurationSec(){return this.state.effectiveBreakDurationSec}set effectiveBreakDurationSec(e){this.state.effectiveBreakDurationSec=e}get adBreakCutSafetyMarginSec(){return this.state.adBreakCutSafetyMarginSec}set adBreakCutSafetyMarginSec(e){this.state.adBreakCutSafetyMarginSec=e}get durationTimer(){return this.state.durationTimer}set durationTimer(e){this.state.durationTimer=e}get adInsertionType(){return this.state.adInsertionType}set adInsertionType(e){this.state.adInsertionType=e}get breakTimebase(){return this.state.breakTimebase}set breakTimebase(e){this.state.breakTimebase=e}constructor(e,t,r,i,n=!1,o,d="parallel",l="overlay",h=s,u=a,S=!1,T=c,M="none"){this.playerContainerCreatedBySDK=!1,this.adMediaContainer=null,this.adPlayer=null,this.adContainer=null,this.companionElement=null,this.staticQuartilesFired=new Set,this.sequencer=null,this.pendingAdError=null,this.preRollHoldActive=!1,this.preRollHoldHandler=null,this.breakContentGateHandler=null,this.destroyed=!1,this.abortingBreak=!1,this.overlayImageEl=null,this.imageAssetTimer=null,this.chainResolver=null,this.transitionPhaseReporter=null,this.chaining=!1,this.diagnoseHandler=null,this.playerContainerOriginalStyle="",this.companionRemoveTimer=null,this.adFadeTimer=null,this.syncing=!1,this.contentVolumeHandler=null,this.adVolumeChangeHandler=null,this.volumeChangeCallback=null,this.stage=null,this.resizeObserver=null,this.contentVideoElement=null,this.contentVideoGeometryHandler=null,this.contentVideoMutationObserver=null,this.resumeGeneration=0,this.singleSurfaceDevice=!1,this.currentSelectedFormat=void 0,this.audioFocus=null,this.state=m(),this.state.playerContainer=r??null,this.clock=T,this.singleSurfaceDevice=S,this.contentPlayer=e,this.adBreakCutSafetyMarginSec=h,this.doubleBoxAudio=u,this.container=t,r&&(this.playerContainer=r),this.createAdAdapter=i,this.debug=n,this.state.gamConfig=o,this.preloadMode=d,this.insertionMode=l,this.pauseAdPresenter=new P({contentPlayer:this.contentPlayer,getStage:()=>this.stage,resolveUri:e=>this.resolveUri(e),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.assetParameters=new y(this.state,{contentPlayer:this.contentPlayer,container:this.container,getGamStreamManager:()=>this.state.gamStreamManager,getCurrentBreak:()=>this.currentBreak,getEffectiveBreakDuration:()=>this.effectiveBreakDurationSec,diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.gamPodBridge=new p(this.state,{contentPlayer:this.contentPlayer,debug:this.debug,getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,isSharedElement:()=>"shared-element"===this.effectiveInsertionMode(),getCurrentBreak:()=>this.currentBreak,getCurrentAsset:()=>this.currentAsset,getEffectiveBreakDuration:()=>this.effectiveBreakDurationSec,getAdPlayerStreamRemainingSec:()=>this.adPlayerStreamRemainingSec(),emitStep:e=>this.emitStep(e),emitAdStart:(e,t,r,s,a)=>this.callbacks?.onAdStart(e,t,r,s,a),emitAdEnd:(e,t,r,s,a)=>this.callbacks?.onAdEnd(e,t,r,s,a),onAdEnded:()=>this.onAdEnded(),pushAssetParameters:(e,t)=>this.pushAssetParameters(e,t),resolveSessionAdTagParameters:()=>this.assetParameters.resolveSessionAdTagParameters(),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.adStage=new A({contentPlayer:this.contentPlayer,container:this.container,getPlayerContainer:()=>this.playerContainer,setPlayerContainer:e=>{this.playerContainer=e},setPlayerContainerOriginalStyle:e=>{this.playerContainerOriginalStyle=e},onPlayerContainerCreated:()=>{this.playerContainerCreatedBySDK=!0},getStage:()=>this.stage,setStage:e=>{this.stage=e},getContentVideo:()=>this.contentVideoElement,setContentVideo:e=>{this.contentVideoElement=e},getAdContainer:()=>this.adContainer,setAdContainer:e=>{this.adContainer=e},getAdMediaContainer:()=>this.adMediaContainer,setAdMediaContainer:e=>{this.adMediaContainer=e},setAdPlayer:e=>{g(this.state),this.adPlayer=e},createAdAdapter:e=>this.createAdAdapter(e),setupEventListeners:()=>this.setupEventListeners(),resizeVast:()=>this.vastAdManager?.resize(),getVariant:e=>this.getVariant(e),getCurrentBreak:()=>this.currentBreak,resolveUri:e=>this.resolveUri(e),getCompanion:()=>this.companionElement,setCompanion:e=>{this.companionElement=e},getOverlayImage:()=>this.overlayImageEl,setOverlayImage:e=>{this.overlayImageEl=e},getImageAssetTimer:()=>this.imageAssetTimer,setImageAssetTimer:e=>{this.imageAssetTimer=e},isChaining:()=>this.chaining,log:(...e)=>this.log(...e)}),this.preloader=new v({state:this.state,clock:this.clock,adStartBudgetMs:AdPlayerController.AD_START_BUDGET_MS,gamPodAdStartBudgetMs:AdPlayerController.GAM_POD_AD_START_BUDGET_MS,minAdStartBudgetMs:AdPlayerController.MIN_AD_START_BUDGET_MS,debug:this.debug,isPlaying:()=>this.isPlaying,preloadMode:this.preloadMode,effectiveInsertionMode:()=>this.effectiveInsertionMode(),getVariant:e=>this.getVariant(e),getAssets:e=>this.getAssets(e),resolveUri:e=>this.resolveUri(e),resolveAssetUri:(e,t)=>this.resolveAssetUri(e,t),getCompanionVariant:e=>this.getVariant(e),getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,buildVastTagUrl:(e,t)=>this.buildVastTagUrl(e,t),resolveChainedSuccessor:e=>this.resolveChainedSuccessor(e),show:()=>this.show(),reapplyAdContainerLayout:e=>this.reapplyAdContainerLayout(e),getCurrentBreak:()=>this.currentBreak,onBreakVisible:e=>this.callbacks?.onBreakVisible?.(e),onAdError:e=>this.onAdError(e),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.presentationModes=new C(this.state,{contentPlayer:this.contentPlayer,getAdPlayer:()=>this.adPlayer,insertionMode:this.insertionMode,getCurrentBreak:()=>this.currentBreak,getCurrentFormat:()=>this.currentSelectedFormat,isSharedElementActive:()=>this.state.sharedAdClaimActive,getVariant:e=>this.getVariant(e),isAdPlaying:()=>this.isAdPlaying(),hasCurrentAsset:()=>null!==this.currentAsset,contentSourceIsReloadable:()=>null!==this.sharedElementPlayer.restorableContentSource(),adoptPictureInPictureMidBreak:()=>this.adoptPictureInPictureMidBreak(),restoreLayout:e=>this.restoreLayout(e),applyLayout:e=>this.applyLayout(e),show:()=>this.show(),playAdThroughContentElement:()=>this.sharedElementPlayer.playAdThroughContentElement(),getContentPositionAtBreakStart:()=>this.state.contentPositionAtBreakStart,setContentPositionAtBreakStart:e=>this.resumeCoordinator.reanchorMidBreak(e),gateContentForBreak:()=>this.gateContentForBreak(),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.resumeCoordinator=new f(this.state,{contentPlayer:this.contentPlayer,clock:this.clock,getInsertionMode:()=>this.effectiveInsertionMode(),gateContentForBreak:()=>this.gateContentForBreak(),clearContentGate:e=>this.clearContentGate(e),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.recoveryDeps={contentPlayer:e,getCallbacks:()=>this.callbacks,preloadMode:d,contentRecovery:M,resumeCoordinator:this.resumeCoordinator,diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)},this.sharedElementPlayer=new k(this.state,{contentPlayer:this.contentPlayer,getAdPlayer:()=>this.adPlayer,resolveAssetUri:(e,t)=>this.resolveAssetUri(e,t),liveEdgeDistanceSec:()=>this.resumeCoordinator.liveEdgeDistanceSec(),rebindContentElementIfSwapped:()=>this.rebindContentElementIfSwapped(),createAdAdapter:(e,t)=>this.createAdAdapter(e,t),reportAdProgress:e=>this.reportAdProgress(e),processTimedMetadata:e=>this.gamPodBridge.processTimedMetadata(e),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e),clearContentGate:()=>this.clearContentGate(),hide:()=>this.hide(),waitForLiveEdge:e=>this.resumeCoordinator.waitForLiveEdge(e),getVariant:e=>this.getVariant(e),getAssets:e=>this.getAssets(e)}),this.variantSelector=new b(this.state,{getEffectiveInsertionMode:()=>this.effectiveInsertionMode(),singleSurfaceDevice:this.singleSurfaceDevice,preloadMode:this.preloadMode,getIsContentPictureInPicture:()=>this.isContentPictureInPicture(),getIsGamReady:()=>this.isGamReady(),getSupportsParallelBuffering:()=>this.contentPlayer.supportsParallelBuffering,diagnose:(e,t,r)=>this.diagnose(e,t,r)}),this.assetPlayback=new B(this.state,{getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,getAdMediaContainer:()=>this.adMediaContainer,clearStaticQuartiles:()=>this.staticQuartilesFired.clear(),getVariant:e=>this.getVariant(e),getGamEventCallbacks:()=>this.gamEventCallbacks,getSequencer:()=>this.sequencer,debug:this.debug,resolveUri:e=>this.resolveUri(e),buildGamUrl:(e,t)=>this.buildGamUrl(e,t),buildVastTagUrl:(e,t)=>this.buildVastTagUrl(e,t),onAdError:e=>this.onAdError(e),onAdEnded:()=>this.onAdEnded(),drive:e=>this.drive(e),clearOverlayImage:()=>this.clearOverlayImage(),revealFirstFrame:()=>this.preloader.revealFirstFrame(),transferPictureInPictureToAd:()=>this.presentationModes.transferPictureInPictureToAd(),isGamPodAsset:e=>this.isGamPodAsset(e),hasGamIdentityMismatch:e=>this.gamPodBridge.hasIdentityMismatch(e),beginGamPodTracking:e=>this.gamPodBridge.beginGamPodTracking(e),recordAdProgress:e=>this.adPlayerEvents.recordAdProgress(e),reportPhase:e=>this.reportPhase(e),armAdStartBudget:e=>this.armAdStartBudget(e),remainingAdStartBudgetMs:()=>this.remainingAdStartBudgetMs(),loadWithinBudget:(e,t)=>this.loadWithinBudget(e,t),waitForFirstFrame:()=>this.waitForFirstFrame(),getOverlayImage:()=>this.overlayImageEl,setOverlayImage:e=>{this.overlayImageEl=e},getImageAssetTimer:()=>this.imageAssetTimer,setImageAssetTimer:e=>{this.imageAssetTimer=e},getVastPodPosition:()=>this.vastPodPosition,setVastPodPosition:e=>{this.vastPodPosition=e},diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.breakSequenceDriver=new E(this.state,{getChainResolver:()=>this.chainResolver,getEffectiveInsertionMode:()=>this.effectiveInsertionMode(),getVastPodPosition:()=>this.vastPodPosition,setVastPodPosition:e=>{this.vastPodPosition=e},getPendingAdError:()=>this.pendingAdError,setPendingAdError:e=>{this.pendingAdError=e},getChaining:()=>this.chaining,setChaining:e=>{this.chaining=e},isExpandingPodAsset:e=>this.isExpandingPodAsset(e),fallBackToPodLevelReporting:()=>this.fallBackToPodLevelReporting(),resetGamPodTracking:()=>this.resetGamPodTracking(),emitGamPodSteps:e=>this.gamPodBridge.emitGamPodSteps(e),playAsset:(e,t,r)=>this.playAsset(e,t,r),endBreak:()=>this.endBreak(),playBreak:(e,t,r)=>this.playBreak(e,t,r),diagnose:(e,t,r)=>this.diagnose(e,t,r),log:(...e)=>this.log(...e)}),this.adPlayerEvents=new F(this.state,{getAdPlayer:()=>this.adPlayer,getContentPlayer:()=>this.contentPlayer,getGamEventCallbacks:()=>this.gamEventCallbacks,getSequencer:()=>this.sequencer,getAudioFocus:()=>this.audioFocus,getSyncing:()=>this.syncing,setSyncing:e=>{this.syncing=e},setAdVolumeChangeHandler:e=>{this.adVolumeChangeHandler=e},setContentVolumeHandler:e=>{this.contentVolumeHandler=e},notifyVolumeChange:()=>this.notifyVolumeChange(),onAdEnded:()=>this.onAdEnded(),processTimedMetadata:e=>this.gamPodBridge.processTimedMetadata(e),toAdError:e=>this.toAdError(e),revealFirstFrame:()=>this.revealFirstFrame(),clearFirstFrameResolver:()=>this.preloader.clearFirstFrameResolver(),drive:e=>this.drive(e),setPendingAdError:e=>{this.pendingAdError=e},log:(...e)=>this.log(...e),maybePrepositionContentForResume:()=>"single-decoder"!==this.preloadMode&&this.resumeCoordinator.maybePrepositionContentForResume(),maybeCatchUpContentForResume:e=>"single-decoder"!==this.preloadMode&&this.resumeCoordinator.maybeCatchUpContentForResume(e),getStaticQuartilesFired:()=>this.staticQuartilesFired,onGamPodAdProgress:e=>this.gamPodBridge.onGamPodAdProgress(e)})}setGamEventCallbacks(e){this.gamPodBridge.setEventCallbacks(e)}setDiagnoseHandler(e){this.diagnoseHandler=e}diagnose(e,t,r){this.diagnoseHandler?.(e,t,r)}holdContentForPreRoll(e){if(this.preRollHoldActive)return;const t=this.getVariant(e);t&&this.shouldPauseContent(t.format)&&(this.preRollHoldActive=!0,this.contentPlayer.pause(),this.preRollHoldHandler=()=>{this.preRollHoldActive&&this.contentPlayer.pause()},this.contentPlayer.on("playing",this.preRollHoldHandler),this.diagnose("DA-PREROLL-CONTENT-HELD","Content held at session start until the pending pre-roll begins.",{breakId:e.id}))}releaseContentHold(){this.preRollHoldActive&&(this.preRollHoldActive=!1,this.preRollHoldHandler&&(this.contentPlayer.off("playing",this.preRollHoldHandler),this.preRollHoldHandler=null))}gateContentForBreak(){this.contentPlayer.pause(),this.breakContentGateHandler||(this.breakContentGateHandler=()=>{this.contentPaused&&!this.state.resumeCatchupActive&&this.contentPlayer.pause()},this.contentPlayer.on("playing",this.breakContentGateHandler))}clearContentGate(e=!1){this.resumeCoordinator.endResumeCatchup(e),this.breakContentGateHandler&&(this.contentPlayer.off("playing",this.breakContentGateHandler),this.breakContentGateHandler=null)}setChainResolver(e){this.chainResolver=e}setResumeCueAnchorResolver(e){this.resumeCoordinator.setCueAnchorResolver(e)}setResumeCueEndResolver(e){this.resumeCoordinator.setCueEndResolver(e)}ingestStreamClockCue(e){this.resumeCoordinator.ingestStreamClockCue(e)}setTransitionPhaseReporter(e){this.transitionPhaseReporter=e}reportPhase(e){this.transitionPhaseReporter?.(e)}setBreakResumePolicy(e,t,r=!1){this.adInsertionType=e,this.breakTimebase=t,this.state.continueContentDuringBreak=r,this.state.continueRefusalReported=!1}initialize(){this.adContainer||(this.setupOverlay(),this.presentationModes.setupPictureInPictureTracking(),"adaptive"===this.insertionMode&&this.presentationModes.setupFullscreenTracking())}async startGamSession(e,t){await this.gamPodBridge.startGamSession(e,t)}endGamSession(){this.gamPodBridge.endGamSession()}setSessionAssetParameters(e){this.assetParameters.setSessionAssetParameters(e)}setManifestAssetParameters(e){this.assetParameters.setManifestAssetParameters(e)}updateAssetParameters(e){this.assetParameters.updateAssetParameters(e)}resolveExternalVendorConfiguration(e){return this.assetParameters.resolveExternalVendorConfiguration(e)}updateAssetParameterMacros(e){this.assetParameters.updateAssetParameterMacros(e)}get updatedAssetParameters(){return this.state.updatedAssetParameters}setSessionAssetParameterMacros(e){this.assetParameters.setSessionAssetParameterMacros(e)}get sessionAssetParameterMacros(){return this.assetParameters.getSessionAssetParameterMacros()}buildVastTagUrl(e,t){return this.assetParameters.buildVastTagUrl(e,t)}pushAssetParameters(e,t){this.assetParameters.pushAssetParameters(e,t)}setupOverlay(){this.adStage.setupOverlay()}isGamPodAsset(e){return this.gamPodBridge.isGamPodAsset(e)}isExpandingPodAsset(e){return this.gamPodBridge.isExpandingPodAsset(e)}fallBackToPodLevelReporting(){this.gamPodBridge.fallBackToPodLevelReporting()}resetGamPodTracking(){this.gamPodBridge.resetGamPodTracking()}emitGamPodSteps(e){this.gamPodBridge.emitGamPodSteps(e)}isGamEnabled(){return this.gamPodBridge.isGamEnabled()}isGamReady(){return this.gamPodBridge.isGamReady()}isOverlayInsertion(){return"overlay"===this.effectiveInsertionMode()}settleAssetProgress(){this.adPlayerEvents.settleAssetProgress()}reportAdProgress(e){this.adPlayerEvents.reportAdProgress(e)}setupEventListeners(){this.adPlayerEvents.setupEventListeners()}async preload(e){return this.preloader.preload(e)}renderLshapeContentBackdrop(e){this.adStage.renderLshapeContentBackdrop(e)}currentInsertionMode(){return this.presentationModes.currentInsertionMode()}effectiveInsertionMode(){return this.presentationModes.effectiveInsertionMode()}isContentPictureInPicture(){return this.presentationModes.isPictureInPicture()}rebindContentElementIfSwapped(){this.presentationModes.rebindContentElementIfSwapped()}teardownFullscreenTracking(){this.presentationModes.teardownFullscreenTracking()}teardownPictureInPictureTracking(){this.presentationModes.teardownPictureInPictureTracking()}isPictureInPicture(){return this.presentationModes.isPictureInPicture()}pictureInPictureOwner(){return this.presentationModes.pictureInPictureOwner()}isShowingAd(){if(!this.isAdPlaying())return!1;const e=this.currentDeclaredFormat();return!n(e,this.isContentPictureInPicture())}currentDeclaredFormat(){return this.currentSelectedFormat??(this.currentBreak?l(this.currentBreak):void 0)}async playBreak(t,s,a){if(this.state.preloadGeneration++,this.resumeGeneration++,!this.sharedElementPlayer.beginSharedActivity())return;this.releaseContentHold(),this.rebindContentElementIfSwapped();const n=a?.effectiveDurationSec??null;this.effectiveBreakDurationSec=null!==n&&n>0?n:null;const d=this.effectiveBreakDurationSec??t.duration;if("shared-element"===this.effectiveInsertionMode())return g(this.state),void await this.sharedElementPlayer.playSharedElementBreak(t,s);if(!this.adPlayer)return void this.log("playBreak called before initialize()");const l=this.getVariant(t);if(!l)return void this.log("No valid variant found for break:",t.id);this.currentBreak=t,this.callbacks=s,this.isPlaying=!0,this.firstFrameGateActive=a?.firstFrameGate??!1,this.firstFrameGateShown=!1;const h=this.continueContentDuringBreakReason(l.format),u=r(t),c=this.shouldPauseContent(l.format)&&"ok"===h&&!u;c||u||this.state.continueRefusalReported||!this.shouldPauseContent(l.format)||(this.state.continueRefusalReported=!0,this.diagnose("DA-CONTINUE-PLAYOUT-REFUSED",`Content will be paused for breaks this session: ${h}`,{reason:h,format:l.format})),this.audioFocus=l.format===e.DOUBLE?this.doubleBoxAudio:c?"ad":null,this.adPlayer&&("content"===this.audioFocus?(this.adPlayer.muted=!0,this.adPlayer.volume=0):(this.adPlayer.muted=this.contentPlayer.muted,this.adPlayer.volume=this.contentPlayer.volume,"ad"===this.audioFocus&&(this.contentPlayer.muted=!0)));const m=this.declaredFormatOf(t);if(this.currentSelectedFormat=m,this.state.pipAdoptedForBreak=i(m,this.isContentPictureInPicture()),this.state.pipAdoptedForBreak&&this.diagnose("DA-PIP-FORMAT-OVERRIDE",`Picture-in-picture: ${m} break plays as single`,{declared:m,effective:e.SINGLE,reason:"picture-in-picture",midBreak:!1}),this.shouldPauseContent(l.format)?(this.resumeCoordinator.captureBreakAnchor(t),c?(this.contentPaused=!1,this.resumeCoordinator.beginContinueContentPlayout()):(this.contentPaused=!0,this.gateContentForBreak())):this.contentPaused=!1,this.applyLayout(l),l.format===e.LSHAPE_CONTENT)return this.renderLshapeContentBackdrop(l),void(d&&d>0?(this.log("Starting duration timer:",d,"seconds"),this.durationTimer=setTimeout(()=>{this.log("Duration timer expired, ending break"),this.endBreak()},1e3*d)):this.endBreak());this.firstFrameGateActive||(this.show(),this.reapplyAdContainerLayout(l));if(0===this.getAssets(t).length)return this.log("No assets in break, ending immediately"),void this.endBreak();{const e=Math.max(0,d||0)+this.adBreakCutSafetyMarginSec;T(this.state,e,()=>{this.log("Break-cut timer expired, ending break"),this.firstFrameRejector?this.onAdError(new R("Break cut before first frame rendered","DA-AD-START-TIMEOUT")):this.sequencer&&this.currentBreak&&this.isPlaying?(this.callbacks?.onBreakCut?.(this.currentBreak),this.drive(this.sequencer.onOutcome({kind:"break-elapsed"}))):this.endBreak()},()=>this.onAdError(new R("Ad playback startup timed out","DA-AD-START-TIMEOUT")))}this.sequencer=new o("overlay",()=>null,this.selectionInputs()),await this.drive(this.sequencer.beginBreak(t)),this.preloadChainedSuccessor(t.id)}get resumeHandoverInMotion(){return this.state.resumeCatchupActive}reapplyAdContainerLayout(e){this.adStage.reapplyAdContainerLayout(e)}adoptPictureInPictureMidBreak(){this.presentationModes.adoptPictureInPictureMidBreak()}async restorePictureInPictureToContent(){await this.presentationModes.restorePictureInPictureToContent()}continueContentDuringBreakReason(e){return this.variantSelector.continueContentDuringBreakReason(e)}shouldPauseContent(t){return t===e.SINGLE||t===e.LSHAPE_AD}selectionInputs(){return this.variantSelector.selectionInputs()}breakNothingToPlayReason(e){return this.variantSelector.breakNothingToPlayReason(e)}unknownVariantFormatsOf(e){return this.variantSelector.unknownVariantFormatsOf(e)}diagnoseUnknownVariantFormats(e){this.variantSelector.diagnoseUnknownVariantFormats(e)}declaredFormatOf(e){const{selected:t,deviceQualified:r}=h(e,this.selectionInputs());return(t??r)?.format??l(e)}getVariant(e){return this.variantSelector.getVariant(e)}applyLayout(e){this.adStage.applyLayout(e)}restoreLayout(e){this.adStage.restoreLayout(e)}getAssets(e){return d(this.getVariant(e))}async playAsset(e,t,r){return this.assetPlayback.playAsset(e,t,r)}clearOverlayImage(){this.adStage.clearOverlayImage()}async showPauseImage(e){return this.pauseAdPresenter.showPauseImage(e)}hidePauseImage(){this.pauseAdPresenter.hidePauseImage()}async drive(e){return this.breakSequenceDriver.drive(e)}emitStep(e){this.breakSequenceDriver.emitStep(e)}async resolveAssetUri(e,t){return this.assetPlayback.resolveAssetUri(e,t)}async buildGamUrl(e,t){return this.gamPodBridge.buildGamUrl(e,t)}resolveUri(e){return this.assetParameters.resolveUri(e)}adPlayerStreamRemainingSec(){return this.assetPlayback.adPlayerStreamRemainingSec()}onAdEnded(){this.currentBreak&&this.isPlaying&&this.sequencer&&(this.settleAssetProgress(),this.drive(this.sequencer.onOutcome({kind:"asset-ended"})))}toAdError(e){return this.assetPlayback.toAdError(e)}onAdError(e){this.adPlayerEvents.onAdError(e)}endBreak(){if(!this.currentBreak)return;this.log("Break ended:",this.currentBreak.id),M(this.state),this.state.gamPodTracker&&this.emitGamPodSteps(this.state.gamPodTracker.finish()),this.resetGamPodTracking(),this.pushAssetParameters(void 0);const e=this.currentBreak,s=this.getVariant(e)?.format;let a=this.abortingBreak?null:this.resolveChainedSuccessor(e.id);if(a){const e=this.breakNothingToPlayReason(a);this.diagnoseUnknownVariantFormats(a),e&&(this.diagnose("DA-BREAK-NO-PLAYABLE-ASSET",`chained break ${a.id} has no playable variant (${e}); it will not begin.`,{breakId:a.id,reason:e}),this.callbacks?.onAdError(a,void 0,new R(`Break ${a.id} has no playable variant (${e})`,"DA-BREAK-NO-PLAYABLE-ASSET")),this.callbacks?.onChainedBreakSkipped?.(a),a=null)}if(a)return void this.advanceToChainedBreak(e,a);if(this.currentSelectedFormat=void 0,this.resumeCoordinator.endContinueContentPlayout(),this.restorePictureInPictureToContent(),this.isPlaying=!1,this.currentBreak=null,this.resumeGeneration++,this.effectiveBreakDurationSec=null,g(this.state),this.preloader.clearWarmedBreaks(),this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.clearFirstFrame("Break ended before first frame"),"ad"===this.audioFocus&&this.adPlayer?(this.contentPlayer.muted=this.adPlayer.muted,this.contentPlayer.volume=this.adPlayer.volume):"content"===this.audioFocus&&this.adPlayer&&(this.adPlayer.muted=this.contentPlayer.muted,this.adPlayer.volume=this.contentPlayer.volume),this.audioFocus=null,this.clearOverlayImage(),this.vastAdManager?.reset(),this.hide(),this.restoreLayout(s),this.adPlayer?.pause(),this.state.sharedAdClaimActive){const t=this.callbacks;return this.sharedElementPlayer.detachSharedAdListeners(),this.abortingBreak=!1,this.state.earlyReturnResumeOffsetSec=null,this.sharedElementPlayer.restoreSharedElementContent(e),void t?.onBreakEnd(e)}const i="recreate"===this.recoveryDeps.contentRecovery&&"function"==typeof this.contentPlayer.recreateMediaPipeline,n="single-decoder"===this.preloadMode||i?this.adPlayer?.unload?.():void 0;if(this.contentPaused&&r(e))this.contentPaused=!1,this.clearContentGate();else if(this.contentPaused){this.contentPaused=!1,this.clearContentGate(this.resumeHandoverInMotion);const r=this.resumeGeneration;S(this.recoveryDeps,{breakInfo:e,earlyReturnOffsetSec:this.state.earlyReturnResumeOffsetSec,isLiveResume:this.breakTimebase===t.WALLCLOCK,released:n,isCurrent:()=>r===this.resumeGeneration})}this.abortingBreak=!1,this.state.earlyReturnResumeOffsetSec=null,this.callbacks?.onBreakEnd(e)}currentAdAsset(){return this.isPlaying?this.currentAsset:null}skipBreak(){this.isPlaying&&(this.log("Skipping break:",this.currentBreak?.id),M(this.state),this.sequencer&&this.currentBreak?this.drive(this.sequencer.onOutcome({kind:"break-elapsed"})):this.endBreak())}abortBreak(e){this.isPlaying&&(this.log("Early return — break removed from manifest:",this.currentBreak?.id),this.state.earlyReturnResumeOffsetSec=Math.max(0,e),this.abortingBreak=!0,M(this.state),this.sequencer&&this.currentBreak?this.drive(this.sequencer.onOutcome({kind:"break-elapsed"})):this.endBreak())}stopActiveBreak(){g(this.state),this.sharedElementPlayer.cancelSharedRestore()&&this.isPlaying&&(this.log("Aborting active break on session end:",this.currentBreak?.id),M(this.state),this.sharedElementPlayer.detachSharedAdListeners(),this.sharedElementPlayer.releaseContentElementAdPlayer(),this.adPlayer?.pause(),this.clearOverlayImage(),this.vastAdManager?.reset(),this.hide(),this.restoreLayout(this.currentBreak?this.getVariant(this.currentBreak)?.format??void 0:void 0),this.isPlaying=!1,this.currentBreak=null,this.currentAsset=null,this.contentPaused=!1,this.clearContentGate(),this.resumeCoordinator.endContinueContentPlayout(),this.effectiveBreakDurationSec=null,this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.clearFirstFrame("Break aborted before first frame"),this.audioFocus=null)}resolveChainedSuccessor(e){return this.breakSequenceDriver.resolveChainedSuccessor(e)}advanceToChainedBreak(e,t){this.breakSequenceDriver.advanceToChainedBreak(e,t)}preloadChainedSuccessor(e){this.preloader.preloadChainedSuccessor(e)}revealFirstFrame(){this.assetPlayback.revealFirstFrame()}armAdStartBudget(e){this.preloader.armAdStartBudget(e)}remainingAdStartBudgetMs(){return this.preloader.remainingAdStartBudgetMs()}loadWithinBudget(e,t){return this.preloader.loadWithinBudget(e,t)}async waitForFirstFrame(){return this.preloader.waitForFirstFrame()}clearFirstFrame(e="Break ended before first frame"){this.preloader.clearFirstFrame(e)}show(){this.adStage.show()}hide(){this.adStage.hide()}isAdPlaying(){return this.isPlaying}get muted(){return"content"===this.audioFocus?this.contentPlayer.muted:"ad"===this.audioFocus?this.adPlayer?this.adPlayer.muted:this.contentPlayer.muted:this.isPlaying&&this.adPlayer?this.adPlayer.muted:this.contentPlayer.muted}set muted(e){if("content"===this.audioFocus)this.contentPlayer.muted=e;else if("ad"===this.audioFocus)this.adPlayer&&(this.adPlayer.muted=e);else{(this.isPlaying&&this.adPlayer?this.adPlayer:this.contentPlayer).muted=e}this.vastAdManager?.setMuted(e),this.notifyVolumeChange()}get volume(){return"content"===this.audioFocus?this.contentPlayer.volume:"ad"===this.audioFocus?this.adPlayer?this.adPlayer.volume:this.contentPlayer.volume:this.isPlaying&&this.adPlayer?this.adPlayer.volume:this.contentPlayer.volume}set volume(e){if("content"===this.audioFocus)this.contentPlayer.volume=e;else if("ad"===this.audioFocus)this.adPlayer&&(this.adPlayer.volume=e);else{(this.isPlaying&&this.adPlayer?this.adPlayer:this.contentPlayer).volume=e}this.vastAdManager?.setVolume(e),this.notifyVolumeChange()}setVolumeChangeCallback(e){this.volumeChangeCallback=e}notifyVolumeChange(){this.volumeChangeCallback?.(this.muted,this.volume)}destroy(){if(this.destroyed)return;if(this.resumeGeneration++,g(this.state),!this.sharedElementPlayer.beginSharedActivity())return;this.destroyed=!0,this.adStage.destroy(),this.resumeCoordinator.cancelResumeLandedProbe(),this.resumeCoordinator.dispose(),this.resumeCoordinator.endResumeCatchup(),this.resumeCoordinator.endContinueContentPlayout(),this.state.resumePrepositionSettle&&(clearTimeout(this.state.resumePrepositionSettle),this.state.resumePrepositionSettle=null),this.releaseContentHold(),this.clearContentGate(),this.clearFirstFrame("Controller destroyed before first frame"),this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.resetGamPodTracking(),M(this.state),this.companionRemoveTimer&&(clearTimeout(this.companionRemoveTimer),this.companionRemoveTimer=null),this.adFadeTimer&&(clearTimeout(this.adFadeTimer),this.adFadeTimer=null),this.adPlayer?.pause(),this.clearOverlayImage(),this.pauseAdPresenter.destroy(),this.contentVolumeHandler&&(this.contentPlayer.off("volumechange",this.contentVolumeHandler),this.contentVolumeHandler=null),this.sharedElementPlayer.detachSharedAdListeners(),this.sharedElementPlayer.releaseContentElementAdPlayer(),this.state.pipTransferredToAd=!1,this.teardownFullscreenTracking(),this.teardownPictureInPictureTracking(),this.adVolumeChangeHandler&&this.adPlayer&&this.adPlayer.off("volumechange",this.adVolumeChangeHandler),this.adVolumeChangeHandler=null,this.hide(),this.adStage.destroy(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.contentVideoMutationObserver?.disconnect(),this.contentVideoMutationObserver=null,this.contentVideoElement&&this.contentVideoGeometryHandler&&(this.contentVideoElement.removeEventListener("loadedmetadata",this.contentVideoGeometryHandler),this.contentVideoElement.removeEventListener("resize",this.contentVideoGeometryHandler)),this.contentVideoElement=null,this.contentVideoGeometryHandler=null;const e=this.adStage.restoreContent(this.playerContainerCreatedBySDK,this.playerContainerOriginalStyle);this.companionElement&&this.companionElement.parentElement&&(this.companionElement.parentElement.removeChild(this.companionElement),this.companionElement=null),this.isPlaying=!1,this.currentBreak=null,this.adContainer&&this.adContainer.parentElement&&this.adContainer.parentElement.removeChild(this.adContainer),!e&&this.stage&&this.stage.parentElement&&this.stage.parentElement.removeChild(this.stage),this.stage=null,this.adContainer=null,this.adMediaContainer=null;try{this.adPlayer?.destroy()}catch(e){this.log("Ad player adapter destroy failed (ignored):",e)}this.adPlayer=null,this.callbacks=null,this.gamPodBridge.destroy(),this.vastAdManager?.destroy(),this.vastAdManager=null,this.log("Ad player destroyed")}log(...e){this.debug&&u("[OptiViewAds:AdPlayerController]",...e)}}AdPlayerController.AD_START_BUDGET_MS=5e3,AdPlayerController.GAM_POD_AD_START_BUDGET_MS=1e4,AdPlayerController.MIN_AD_START_BUDGET_MS=3e3;
|
|
1
|
+
import{BreakFormat as e,Timebase as t,isPostRollBreak as s}from"../types/BreakManifest";import{DEFAULT_AD_BREAK_CUT_SAFETY_MARGIN_SEC as r,DEFAULT_DOUBLE_BOX_AUDIO as a}from"../types/OptiViewAdsConfig";import{pipOverridesFormat as i,pipSuppressesBackdrop as n}from"./pictureInPicture";import{AdBreakSequencer as o,assetsOfVariant as d,resolveBreakFormat as l}from"./AdBreakSequencer";import{selectVariantDetailed as h}from"./selectVariant";import{debugLog as u}from"../diagnostics/debugLog";import{systemClock as c}from"./BreakScheduler";import{createAdPlayerState as m,invalidateMediaPreload as g}from"./adPlayer/AdPlayerState";import{PauseAdPresenter as P}from"./adPlayer/PauseAdPresenter";import{AssetParameterResolver as y}from"./adPlayer/AssetParameterResolver";import{GamPodBridge as p}from"./adPlayer/GamPodBridge";import{AdStage as A}from"./adPlayer/AdStage";import{createDomPresentationHost as C,toPresentationSurfaces as v}from"./adPlayer/presentation/DomPresentationHost";import{AdPreloader as k}from"./adPlayer/AdPreloader";import{PresentationModeTracker as f}from"./adPlayer/PresentationModeTracker";import{SharedElementBreakPlayer as S}from"./adPlayer/SharedElementBreakPlayer";import{ContentResumeCoordinator as B}from"./adPlayer/ContentResumeCoordinator";import{resumeContentAfterBreak as b}from"./adPlayer/ContentRecovery";import{AssetPlayback as E}from"./adPlayer/AssetPlayback";import{BreakSequenceDriver as F}from"./adPlayer/BreakSequenceDriver";import{VariantSelector as M}from"./adPlayer/VariantSelector";import{AdPlayerEvents as T}from"./adPlayer/AdPlayerEvents";import{armPlaybackCutoff as R,clearPlaybackCutoff as I}from"./adPlayer/PlaybackCutoff";import{AdError as G}from"../types/AdError";import{SuccessorQueue as V}from"./adPlayer/SuccessorQueue";export class AdPlayerController{get contentPaused(){return this.state.contentPaused}set contentPaused(e){this.state.contentPaused=e}get firstFrameGateActive(){return this.state.firstFrameGateActive}set firstFrameGateActive(e){this.state.firstFrameGateActive=e}get firstFrameGateShown(){return this.state.firstFrameGateShown}set firstFrameGateShown(e){this.state.firstFrameGateShown=e}get firstFrameRejector(){return this.state.firstFrameRejector}set firstFrameRejector(e){this.state.firstFrameRejector=e}get gamEventCallbacks(){return this.gamPodBridge.eventCallbacks}get vastAdManager(){return this.state.vastAdManager}set vastAdManager(e){this.state.vastAdManager=e}get currentBreak(){return this.state.currentBreak}set currentBreak(e){this.state.currentBreak=e}get currentAsset(){return this.state.currentAsset}set currentAsset(e){this.state.currentAsset=e}get callbacks(){return this.state.callbacks}set callbacks(e){this.state.callbacks=e}get isPlaying(){return this.state.isPlaying}set isPlaying(e){this.state.isPlaying=e}get effectiveBreakDurationSec(){return this.state.effectiveBreakDurationSec}set effectiveBreakDurationSec(e){this.state.effectiveBreakDurationSec=e}get adBreakCutSafetyMarginSec(){return this.state.adBreakCutSafetyMarginSec}set adBreakCutSafetyMarginSec(e){this.state.adBreakCutSafetyMarginSec=e}get durationTimer(){return this.state.durationTimer}set durationTimer(e){this.state.durationTimer=e}get adInsertionType(){return this.state.adInsertionType}set adInsertionType(e){this.state.adInsertionType=e}get breakTimebase(){return this.state.breakTimebase}set breakTimebase(e){this.state.breakTimebase=e}constructor(e,t,s,i,n=!1,o,d="parallel",l="overlay",h=r,u=a,b=!1,R=c,I="none"){this.playerContainerCreatedBySDK=!1,this.adMediaContainer=null,this.adPlayer=null,this.adContainer=null,this.companionElement=null,this.staticQuartilesFired=new Set,this.sequencer=null,this.pendingAdError=null,this.preRollHoldActive=!1,this.preRollHoldHandler=null,this.breakContentGateHandler=null,this.destroyed=!1,this.abortingBreak=!1,this.overlayImageEl=null,this.imageAssetTimer=null,this.chainResolver=null,this.transitionPhaseReporter=null,this.chaining=!1,this.diagnoseHandler=null,this.playerContainerOriginalStyle="",this.companionRemoveTimer=null,this.adFadeTimer=null,this.syncing=!1,this.contentVolumeHandler=null,this.adVolumeChangeHandler=null,this.volumeChangeCallback=null,this.stage=null,this.resizeObserver=null,this.contentVideoElement=null,this.contentVideoGeometryHandler=null,this.contentVideoMutationObserver=null,this.resumeGeneration=0,this.singleSurfaceDevice=!1,this.currentSelectedFormat=void 0,this.audioFocus=null,this.state=m(),this.state.playerContainer=s??null,this.clock=R,this.singleSurfaceDevice=b,this.contentPlayer=e,this.adBreakCutSafetyMarginSec=h,this.doubleBoxAudio=u,this.container=t,s&&(this.playerContainer=s),this.createAdAdapter=i,this.debug=n,this.state.gamConfig=o,this.preloadMode=d,this.insertionMode=l,this.pauseAdPresenter=new P({contentPlayer:this.contentPlayer,getStage:()=>this.stage,resolveUri:e=>this.resolveUri(e),buildStaticAssetUrl:(e,t)=>this.buildStaticAssetUrl(e,t),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.assetParameters=new y(this.state,{contentPlayer:this.contentPlayer,container:this.container,getGamStreamManager:()=>this.state.gamStreamManager,getCurrentBreak:()=>this.currentBreak,getEffectiveBreakDuration:()=>this.effectiveBreakDurationSec,diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.gamPodBridge=new p(this.state,{contentPlayer:this.contentPlayer,debug:this.debug,getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,isSharedElement:()=>"shared-element"===this.effectiveInsertionMode(),getCurrentBreak:()=>this.currentBreak,getCurrentAsset:()=>this.currentAsset,getEffectiveBreakDuration:()=>this.effectiveBreakDurationSec,getAdPlayerStreamRemainingSec:()=>this.adPlayerStreamRemainingSec(),emitStep:e=>this.emitStep(e),emitAdStart:(e,t,s,r,a)=>this.callbacks?.onAdStart(e,t,s,r,a),emitAdEnd:(e,t,s,r,a)=>this.callbacks?.onAdEnd(e,t,s,r,a),onAdEnded:()=>this.onAdEnded(),pushAssetParameters:(e,t)=>this.pushAssetParameters(e,t),assetParameterResolver:this.assetParameters,diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.adStage=new A({contentPlayer:this.contentPlayer,container:this.container,getPlayerContainer:()=>this.playerContainer,setPlayerContainer:e=>{this.playerContainer=e},setPlayerContainerOriginalStyle:e=>{this.playerContainerOriginalStyle=e},onPlayerContainerCreated:()=>{this.playerContainerCreatedBySDK=!0},getStage:()=>this.stage,setStage:e=>{this.stage=e},getContentVideo:()=>this.contentVideoElement,setContentVideo:e=>{this.contentVideoElement=e},getAdContainer:()=>this.adContainer,setAdContainer:e=>{this.adContainer=e},getAdMediaContainer:()=>this.adMediaContainer,setAdMediaContainer:e=>{this.adMediaContainer=e},setAdPlayer:e=>{g(this.state),this.adPlayer=e},createAdAdapter:e=>this.createAdAdapter(e),setupEventListeners:()=>this.setupEventListeners(),resizeVast:()=>this.vastAdManager?.resize(),getVariant:e=>this.getVariant(e),getCurrentBreak:()=>this.currentBreak,buildStaticAssetUrl:(e,t)=>this.buildStaticAssetUrl(e,t),getCompanion:()=>this.companionElement,setCompanion:e=>{this.companionElement=e},getOverlayImage:()=>this.overlayImageEl,setOverlayImage:e=>{this.overlayImageEl=e},getImageAssetTimer:()=>this.imageAssetTimer,setImageAssetTimer:e=>{this.imageAssetTimer=e},isChaining:()=>this.chaining,log:(...e)=>this.log(...e),presentationHost:C(()=>v(this.playerContainer,this.adContainer,this.stage))}),this.preloader=new k({state:this.state,clock:this.clock,adStartBudgetMs:AdPlayerController.AD_START_BUDGET_MS,gamPodAdStartBudgetMs:AdPlayerController.GAM_POD_AD_START_BUDGET_MS,minAdStartBudgetMs:AdPlayerController.MIN_AD_START_BUDGET_MS,debug:this.debug,isPlaying:()=>this.isPlaying,preloadMode:this.preloadMode,effectiveInsertionMode:()=>this.effectiveInsertionMode(),getVariant:e=>this.getVariant(e),getAssets:e=>this.getAssets(e),buildStaticAssetUrl:(e,t)=>this.buildStaticAssetUrl(e,t),resolveAssetUri:(e,t,s)=>this.resolveAssetUri(e,t,s),getCompanionVariant:e=>this.getVariant(e),getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,buildVastTagUrl:(e,t)=>this.buildVastTagUrl(e,t),resolveChainedSuccessor:e=>this.resolveChainedSuccessor(e),show:()=>this.show(),reapplyAdContainerLayout:e=>this.reapplyAdContainerLayout(e),getCurrentBreak:()=>this.currentBreak,onBreakVisible:e=>this.callbacks?.onBreakVisible?.(e),onAdError:e=>this.onAdError(e),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.presentationModes=new f(this.state,{contentPlayer:this.contentPlayer,getAdPlayer:()=>this.adPlayer,insertionMode:this.insertionMode,getCurrentBreak:()=>this.currentBreak,getCurrentFormat:()=>this.currentSelectedFormat,isSharedElementActive:()=>this.state.sharedAdClaimActive,getVariant:e=>this.getVariant(e),isAdPlaying:()=>this.isAdPlaying(),hasCurrentAsset:()=>null!==this.currentAsset,contentSourceIsReloadable:()=>null!==this.sharedElementPlayer.restorableContentSource(),adoptPictureInPictureMidBreak:()=>this.adoptPictureInPictureMidBreak(),restoreLayout:()=>this.restoreLayout(),applyLayout:e=>this.applyLayout(e),show:()=>this.show(),playAdThroughContentElement:()=>this.sharedElementPlayer.playAdThroughContentElement(),getContentPositionAtBreakStart:()=>this.state.contentPositionAtBreakStart,setContentPositionAtBreakStart:e=>this.resumeCoordinator.reanchorMidBreak(e),gateContentForBreak:()=>this.gateContentForBreak(),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.resumeCoordinator=new B(this.state,{contentPlayer:this.contentPlayer,clock:this.clock,getInsertionMode:()=>this.effectiveInsertionMode(),gateContentForBreak:()=>this.gateContentForBreak(),clearContentGate:e=>this.clearContentGate(e),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.recoveryDeps={contentPlayer:e,getCallbacks:()=>this.callbacks,preloadMode:d,contentRecovery:I,resumeCoordinator:this.resumeCoordinator,diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)},this.sharedElementPlayer=new S(this.state,{contentPlayer:this.contentPlayer,getAdPlayer:()=>this.adPlayer,resolveAssetUri:(e,t)=>this.resolveAssetUri(e,t),liveEdgeDistanceSec:()=>this.resumeCoordinator.liveEdgeDistanceSec(),rebindContentElementIfSwapped:()=>this.rebindContentElementIfSwapped(),createAdAdapter:(e,t)=>this.createAdAdapter(e,t),reportAdProgress:e=>this.reportAdProgress(e),processTimedMetadata:e=>this.gamPodBridge.processTimedMetadata(e),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e),clearContentGate:()=>this.clearContentGate(),hide:()=>this.hide(),waitForLiveEdge:e=>this.resumeCoordinator.waitForLiveEdge(e),getVariant:e=>this.getVariant(e),getAssets:e=>this.getAssets(e)}),this.variantSelector=new M(this.state,{getEffectiveInsertionMode:()=>this.effectiveInsertionMode(),singleSurfaceDevice:this.singleSurfaceDevice,preloadMode:this.preloadMode,getIsContentPictureInPicture:()=>this.isContentPictureInPicture(),getIsGamReady:()=>this.isGamReady(),getSupportsParallelBuffering:()=>this.contentPlayer.supportsParallelBuffering,diagnose:(e,t,s)=>this.diagnose(e,t,s)}),this.successorQueue=new V({getAdPlayer:()=>this.adPlayer,isEnabled:()=>"parallel"===this.preloadMode&&"overlay"===this.effectiveInsertionMode()&&!this.state.sharedAdClaimActive,buildStaticAssetUrl:(e,t)=>this.buildStaticAssetUrl(e,t),getCallbacks:()=>this.state.callbacks,log:(...e)=>this.log(...e)}),this.assetPlayback=new E(this.state,{getAdPlayer:()=>this.adPlayer,getAdContainer:()=>this.adContainer,getAdMediaContainer:()=>this.adMediaContainer,clearStaticQuartiles:()=>this.staticQuartilesFired.clear(),getVariant:e=>this.getVariant(e),getGamEventCallbacks:()=>this.gamEventCallbacks,getSequencer:()=>this.sequencer,debug:this.debug,buildStaticAssetUrl:(e,t)=>this.buildStaticAssetUrl(e,t),buildGamUrl:(e,t)=>this.buildGamUrl(e,t),buildVastTagUrl:(e,t)=>this.buildVastTagUrl(e,t),onAdError:e=>this.onAdError(e),onAdEnded:()=>this.onAdEnded(),drive:e=>this.drive(e),clearOverlayImage:()=>this.clearOverlayImage(),revealFirstFrame:()=>this.preloader.revealFirstFrame(),transferPictureInPictureToAd:()=>this.presentationModes.transferPictureInPictureToAd(),isGamPodAsset:e=>this.isGamPodAsset(e),hasGamIdentityMismatch:e=>this.gamPodBridge.hasIdentityMismatch(e),beginGamPodTracking:e=>this.gamPodBridge.beginGamPodTracking(e),recordAdProgress:e=>this.adPlayerEvents.recordAdProgress(e),reportPhase:e=>this.reportPhase(e),armAdStartBudget:e=>this.armAdStartBudget(e),takeQueuedSuccessor:(e,t,s)=>this.successorQueue.take(e,t,s),queueUpcomingAd:()=>{const e=this.sequencer?.upcomingAsset();e&&this.currentBreak&&this.successorQueue.prepare(this.currentBreak,e,!1)},remainingAdStartBudgetMs:()=>this.remainingAdStartBudgetMs(),loadWithinBudget:(e,t)=>this.loadWithinBudget(e,t),waitForFirstFrame:()=>this.waitForFirstFrame(),getOverlayImage:()=>this.overlayImageEl,setOverlayImage:e=>{this.overlayImageEl=e},getImageAssetTimer:()=>this.imageAssetTimer,setImageAssetTimer:e=>{this.imageAssetTimer=e},getVastPodPosition:()=>this.vastPodPosition,setVastPodPosition:e=>{this.vastPodPosition=e},diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.breakSequenceDriver=new F(this.state,{successorQueue:this.successorQueue,getAssets:e=>this.getAssets(e),getChainResolver:()=>this.chainResolver,getEffectiveInsertionMode:()=>this.effectiveInsertionMode(),getVastPodPosition:()=>this.vastPodPosition,setVastPodPosition:e=>{this.vastPodPosition=e},getPendingAdError:()=>this.pendingAdError,setPendingAdError:e=>{this.pendingAdError=e},getChaining:()=>this.chaining,setChaining:e=>{this.chaining=e},isExpandingPodAsset:e=>this.isExpandingPodAsset(e),fallBackToPodLevelReporting:()=>this.fallBackToPodLevelReporting(),resetGamPodTracking:()=>this.resetGamPodTracking(),emitGamPodSteps:e=>this.gamPodBridge.emitGamPodSteps(e),playAsset:(e,t,s)=>this.playAsset(e,t,s),endBreak:()=>this.endBreak(),playBreak:(e,t,s)=>this.playBreak(e,t,s),diagnose:(e,t,s)=>this.diagnose(e,t,s),log:(...e)=>this.log(...e)}),this.adPlayerEvents=new T(this.state,{getAdPlayer:()=>this.adPlayer,getContentPlayer:()=>this.contentPlayer,getGamEventCallbacks:()=>this.gamEventCallbacks,getSequencer:()=>this.sequencer,getAudioFocus:()=>this.audioFocus,getSyncing:()=>this.syncing,setSyncing:e=>{this.syncing=e},setAdVolumeChangeHandler:e=>{this.adVolumeChangeHandler=e},setContentVolumeHandler:e=>{this.contentVolumeHandler=e},notifyVolumeChange:()=>this.notifyVolumeChange(),onAdEnded:()=>this.onAdEnded(),processTimedMetadata:e=>this.gamPodBridge.processTimedMetadata(e),toAdError:e=>this.toAdError(e),revealFirstFrame:()=>this.revealFirstFrame(),clearFirstFrameResolver:()=>this.preloader.clearFirstFrameResolver(),drive:e=>this.drive(e),setPendingAdError:e=>{this.pendingAdError=e},dropQueuedAd:()=>this.successorQueue.drop(),log:(...e)=>this.log(...e),maybePrepositionContentForResume:()=>"single-decoder"!==this.preloadMode&&this.resumeCoordinator.maybePrepositionContentForResume(),maybeCatchUpContentForResume:e=>"single-decoder"!==this.preloadMode&&this.resumeCoordinator.maybeCatchUpContentForResume(e),getStaticQuartilesFired:()=>this.staticQuartilesFired,onGamPodAdProgress:e=>this.gamPodBridge.onGamPodAdProgress(e)})}setGamEventCallbacks(e){this.gamPodBridge.setEventCallbacks(e)}setDiagnoseHandler(e){this.diagnoseHandler=e}diagnose(e,t,s){this.diagnoseHandler?.(e,t,s)}holdContentForPreRoll(e){if(this.preRollHoldActive)return;const t=this.getVariant(e);t&&this.shouldPauseContent(t.format)&&(this.preRollHoldActive=!0,this.contentPlayer.pause(),this.preRollHoldHandler=()=>{this.preRollHoldActive&&this.contentPlayer.pause()},this.contentPlayer.on("playing",this.preRollHoldHandler),this.diagnose("DA-PREROLL-CONTENT-HELD","Content held at session start until the pending pre-roll begins.",{breakId:e.id}))}releaseContentHold(){this.preRollHoldActive&&(this.preRollHoldActive=!1,this.preRollHoldHandler&&(this.contentPlayer.off("playing",this.preRollHoldHandler),this.preRollHoldHandler=null))}gateContentForBreak(){this.contentPlayer.pause(),this.breakContentGateHandler||(this.breakContentGateHandler=()=>{this.contentPaused&&!this.state.resumeCatchupActive&&this.contentPlayer.pause()},this.contentPlayer.on("playing",this.breakContentGateHandler))}clearContentGate(e=!1){this.resumeCoordinator.endResumeCatchup(e),this.breakContentGateHandler&&(this.contentPlayer.off("playing",this.breakContentGateHandler),this.breakContentGateHandler=null)}setChainResolver(e){this.chainResolver=e}onChainSuccessorChanged(){this.sequencer&&this.currentBreak&&this.isPlaying&&this.drive(this.sequencer.onOutcome({kind:"successor-changed"}),!0)}setResumeCueAnchorResolver(e){this.resumeCoordinator.setCueAnchorResolver(e)}setResumeCueEndResolver(e){this.resumeCoordinator.setCueEndResolver(e)}ingestStreamClockCue(e){this.resumeCoordinator.ingestStreamClockCue(e)}setTransitionPhaseReporter(e){this.transitionPhaseReporter=e}reportPhase(e){this.transitionPhaseReporter?.(e)}setBreakResumePolicy(e,t,s=!1){this.adInsertionType=e,this.breakTimebase=t,this.state.continueContentDuringBreak=s,this.state.continueRefusalReported=!1}initialize(){this.adContainer||(this.setupOverlay(),this.presentationModes.setupPictureInPictureTracking(),"adaptive"===this.insertionMode&&this.presentationModes.setupFullscreenTracking())}async startGamSession(e,t){await this.gamPodBridge.startGamSession(e,t)}endGamSession(){this.gamPodBridge.endGamSession()}setSessionAssetParameters(e){this.assetParameters.setSessionAssetParameters(e)}setManifestAssetParameters(e){this.assetParameters.setManifestAssetParameters(e)}updateAssetParameters(e){this.assetParameters.updateAssetParameters(e)}resolveExternalVendorConfiguration(e){return this.assetParameters.resolveExternalVendorConfiguration(e)}updateAssetParameterMacros(e){this.assetParameters.updateAssetParameterMacros(e)}get updatedAssetParameters(){return this.state.updatedAssetParameters}setSessionAssetParameterMacros(e){this.assetParameters.setSessionAssetParameterMacros(e)}get sessionAssetParameterMacros(){return this.assetParameters.getSessionAssetParameterMacros()}buildVastTagUrl(e,t){return this.assetParameters.buildVastTagUrl(e,t)}buildStaticAssetUrl(e,t){return this.assetParameters.buildStaticAssetUrl(e,t)}pushAssetParameters(e,t){this.assetParameters.pushAssetParameters(e,t)}setupOverlay(){this.adStage.setupOverlay()}isGamPodAsset(e){return this.gamPodBridge.isGamPodAsset(e)}isExpandingPodAsset(e){return this.gamPodBridge.isExpandingPodAsset(e)}fallBackToPodLevelReporting(){this.gamPodBridge.fallBackToPodLevelReporting()}resetGamPodTracking(){this.gamPodBridge.resetGamPodTracking()}emitGamPodSteps(e){this.gamPodBridge.emitGamPodSteps(e)}isGamEnabled(){return this.gamPodBridge.isGamEnabled()}isGamReady(){return this.gamPodBridge.isGamReady()}isOverlayInsertion(){return"overlay"===this.effectiveInsertionMode()}settleAssetProgress(){this.adPlayerEvents.settleAssetProgress()}reportAdProgress(e){this.adPlayerEvents.reportAdProgress(e)}setupEventListeners(){this.adPlayerEvents.setupEventListeners()}async preload(e){return this.preloader.preload(e)}renderLshapeContentBackdrop(e){this.adStage.renderLshapeContentBackdrop(e)}currentInsertionMode(){return this.presentationModes.currentInsertionMode()}effectiveInsertionMode(){return this.presentationModes.effectiveInsertionMode()}isContentPictureInPicture(){return this.presentationModes.isPictureInPicture()}rebindContentElementIfSwapped(){this.presentationModes.rebindContentElementIfSwapped()}teardownFullscreenTracking(){this.presentationModes.teardownFullscreenTracking()}teardownPictureInPictureTracking(){this.presentationModes.teardownPictureInPictureTracking()}isPictureInPicture(){return this.presentationModes.isPictureInPicture()}pictureInPictureOwner(){return this.presentationModes.pictureInPictureOwner()}isShowingAd(){if(!this.isAdPlaying())return!1;const e=this.currentDeclaredFormat();return!n(e,this.isContentPictureInPicture())}currentDeclaredFormat(){return this.currentSelectedFormat??(this.currentBreak?l(this.currentBreak):void 0)}async playBreak(t,r,a){if(this.state.preloadGeneration++,this.resumeGeneration++,!this.sharedElementPlayer.beginSharedActivity())return;this.releaseContentHold(),this.rebindContentElementIfSwapped();const n=a?.effectiveDurationSec??null;this.effectiveBreakDurationSec=null!==n&&n>0?n:null;const d=this.effectiveBreakDurationSec??t.duration;if("shared-element"===this.effectiveInsertionMode())return g(this.state),void await this.sharedElementPlayer.playSharedElementBreak(t,r);if(!this.adPlayer)return void this.log("playBreak called before initialize()");const l=this.getVariant(t);if(!l)return void this.log("No valid variant found for break:",t.id);this.currentBreak=t,this.callbacks=r,this.isPlaying=!0,this.firstFrameGateActive=a?.firstFrameGate??!1,this.firstFrameGateShown=!1;const h=this.continueContentDuringBreakReason(l.format),u=s(t),c=this.shouldPauseContent(l.format)&&"ok"===h&&!u;c||u||this.state.continueRefusalReported||!this.shouldPauseContent(l.format)||(this.state.continueRefusalReported=!0,this.diagnose("DA-CONTINUE-PLAYOUT-REFUSED",`Content will be paused for breaks this session: ${h}`,{reason:h,format:l.format})),this.audioFocus=l.format===e.DOUBLE?this.doubleBoxAudio:c?"ad":null,this.adPlayer&&("content"===this.audioFocus?(this.adPlayer.muted=!0,this.adPlayer.volume=0):(this.adPlayer.muted=this.contentPlayer.muted,this.adPlayer.volume=this.contentPlayer.volume,"ad"===this.audioFocus&&(this.contentPlayer.muted=!0)));const m=this.declaredFormatOf(t);if(this.currentSelectedFormat=m,this.state.pipAdoptedForBreak=i(m,this.isContentPictureInPicture()),this.state.pipAdoptedForBreak&&this.diagnose("DA-PIP-FORMAT-OVERRIDE",`Picture-in-picture: ${m} break plays as single`,{declared:m,effective:e.SINGLE,reason:"picture-in-picture",midBreak:!1}),this.shouldPauseContent(l.format)?(this.resumeCoordinator.captureBreakAnchor(t),c?(this.contentPaused=!1,this.resumeCoordinator.beginContinueContentPlayout()):(this.contentPaused=!0,this.gateContentForBreak())):this.contentPaused=!1,this.applyLayout(l),l.format===e.LSHAPE_CONTENT)return this.renderLshapeContentBackdrop(l),void(d&&d>0?(this.log("Starting duration timer:",d,"seconds"),this.durationTimer=setTimeout(()=>{this.log("Duration timer expired, ending break"),this.endBreak()},1e3*d)):this.endBreak());this.firstFrameGateActive||(this.show(),this.reapplyAdContainerLayout(l));if(0===this.getAssets(t).length)return this.log("No assets in break, ending immediately"),void this.endBreak();{const e=Math.max(0,d||0)+this.adBreakCutSafetyMarginSec;R(this.state,e,()=>{this.log("Break-cut timer expired, ending break"),this.firstFrameRejector?this.onAdError(new G("Break cut before first frame rendered","DA-AD-START-TIMEOUT")):this.sequencer&&this.currentBreak&&this.isPlaying?(this.callbacks?.onBreakCut?.(this.currentBreak),this.drive(this.sequencer.onOutcome({kind:"break-elapsed"}))):this.endBreak()},()=>this.onAdError(new G("Ad playback startup timed out","DA-AD-START-TIMEOUT")))}this.sequencer=new o("overlay",()=>null,this.selectionInputs(),e=>this.resolveChainedSuccessor(e)),await this.drive(this.sequencer.beginBreak(t)),this.preloadChainedSuccessor(t.id)}get resumeHandoverInMotion(){return this.state.resumeCatchupActive}reapplyAdContainerLayout(e){this.adStage.reapplyAdContainerLayout(e)}adoptPictureInPictureMidBreak(){this.presentationModes.adoptPictureInPictureMidBreak()}async restorePictureInPictureToContent(){await this.presentationModes.restorePictureInPictureToContent()}continueContentDuringBreakReason(e){return this.variantSelector.continueContentDuringBreakReason(e)}shouldPauseContent(t){return t===e.SINGLE||t===e.LSHAPE_AD}selectionInputs(){return this.variantSelector.selectionInputs()}breakNothingToPlayReason(e){return this.variantSelector.breakNothingToPlayReason(e)}unknownVariantFormatsOf(e){return this.variantSelector.unknownVariantFormatsOf(e)}diagnoseUnknownVariantFormats(e){this.variantSelector.diagnoseUnknownVariantFormats(e)}declaredFormatOf(e){const{selected:t,deviceQualified:s}=h(e,this.selectionInputs());return(t??s)?.format??l(e)}getVariant(e){return this.variantSelector.getVariant(e)}applyLayout(e){this.adStage.applyLayout(e)}restoreLayout(){this.adStage.restoreLayout()}getAssets(e){return d(this.getVariant(e))}async playAsset(e,t,s){return this.assetPlayback.playAsset(e,t,s)}clearOverlayImage(){this.adStage.clearOverlayImage()}async showPauseImage(e){return this.pauseAdPresenter.showPauseImage(e)}hidePauseImage(){this.pauseAdPresenter.hidePauseImage()}async drive(e,t=!1){return this.breakSequenceDriver.drive(e,t)}emitStep(e){this.breakSequenceDriver.emitStep(e)}async resolveAssetUri(e,t,s){return this.assetPlayback.resolveAssetUri(e,t,s)}async buildGamUrl(e,t){return this.gamPodBridge.buildGamUrl(e,t)}resolveUri(e){return this.assetParameters.resolveUri(e)}adPlayerStreamRemainingSec(){return this.assetPlayback.adPlayerStreamRemainingSec()}onAdEnded(){this.currentBreak&&this.isPlaying&&this.sequencer&&(this.settleAssetProgress(),this.drive(this.sequencer.onOutcome({kind:"asset-ended"})))}toAdError(e){return this.assetPlayback.toAdError(e)}onAdError(e){this.adPlayerEvents.onAdError(e)}endBreak(){if(!this.currentBreak)return;this.log("Break ended:",this.currentBreak.id),I(this.state),this.state.gamPodTracker&&this.emitGamPodSteps(this.state.gamPodTracker.finish()),this.resetGamPodTracking(),this.pushAssetParameters(void 0);const e=this.currentBreak;let r=this.abortingBreak?null:this.resolveChainedSuccessor(e.id);if(r){const e=this.breakNothingToPlayReason(r);this.diagnoseUnknownVariantFormats(r),e&&(this.diagnose("DA-BREAK-NO-PLAYABLE-ASSET",`chained break ${r.id} has no playable variant (${e}); it will not begin.`,{breakId:r.id,reason:e}),this.callbacks?.onAdError(r,void 0,new G(`Break ${r.id} has no playable variant (${e})`,"DA-BREAK-NO-PLAYABLE-ASSET")),this.callbacks?.onChainedBreakSkipped?.(r),r=null)}if(r)return void this.advanceToChainedBreak(e,r);if(this.currentSelectedFormat=void 0,this.resumeCoordinator.endContinueContentPlayout(),this.restorePictureInPictureToContent(),this.isPlaying=!1,this.currentBreak=null,this.resumeGeneration++,this.effectiveBreakDurationSec=null,g(this.state),this.preloader.clearWarmedBreaks(),this.successorQueue.reset(),this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.clearFirstFrame("Break ended before first frame"),"ad"===this.audioFocus&&this.adPlayer?(this.contentPlayer.muted=this.adPlayer.muted,this.contentPlayer.volume=this.adPlayer.volume):"content"===this.audioFocus&&this.adPlayer&&(this.adPlayer.muted=this.contentPlayer.muted,this.adPlayer.volume=this.contentPlayer.volume),this.audioFocus=null,this.clearOverlayImage(),this.vastAdManager?.reset(),this.hide(),this.restoreLayout(),this.adPlayer?.pause(),this.state.sharedAdClaimActive){const t=this.callbacks;return this.sharedElementPlayer.detachSharedAdListeners(),this.abortingBreak=!1,this.state.earlyReturnResumeOffsetSec=null,this.sharedElementPlayer.restoreSharedElementContent(e),void t?.onBreakEnd(e)}const a="recreate"===this.recoveryDeps.contentRecovery&&"function"==typeof this.contentPlayer.recreateMediaPipeline,i="single-decoder"===this.preloadMode||a?this.adPlayer?.unload?.():void 0;if(this.contentPaused&&s(e))this.contentPaused=!1,this.clearContentGate();else if(this.contentPaused){this.contentPaused=!1,this.clearContentGate(this.resumeHandoverInMotion);const s=this.resumeGeneration;b(this.recoveryDeps,{breakInfo:e,earlyReturnOffsetSec:this.state.earlyReturnResumeOffsetSec,isLiveResume:this.breakTimebase===t.WALLCLOCK,released:i,isCurrent:()=>s===this.resumeGeneration})}this.abortingBreak=!1,this.state.earlyReturnResumeOffsetSec=null,this.callbacks?.onBreakEnd(e)}currentAdAsset(){return this.isPlaying?this.currentAsset:null}skipBreak(){this.isPlaying&&(this.log("Skipping break:",this.currentBreak?.id),I(this.state),this.sequencer&&this.currentBreak?this.drive(this.sequencer.onOutcome({kind:"break-elapsed"})):this.endBreak())}abortBreak(e){this.isPlaying&&(this.log("Early return — break removed from manifest:",this.currentBreak?.id),this.state.earlyReturnResumeOffsetSec=Math.max(0,e),this.abortingBreak=!0,I(this.state),this.sequencer&&this.currentBreak?this.drive(this.sequencer.onOutcome({kind:"break-elapsed"})):this.endBreak())}stopActiveBreak(){g(this.state),this.successorQueue.reset(),this.sharedElementPlayer.cancelSharedRestore()&&this.isPlaying&&(this.log("Aborting active break on session end:",this.currentBreak?.id),I(this.state),this.sharedElementPlayer.detachSharedAdListeners(),this.sharedElementPlayer.releaseContentElementAdPlayer(),this.adPlayer?.pause(),this.clearOverlayImage(),this.vastAdManager?.reset(),this.hide(),this.restoreLayout(),this.isPlaying=!1,this.currentBreak=null,this.currentAsset=null,this.contentPaused=!1,this.clearContentGate(),this.resumeCoordinator.endContinueContentPlayout(),this.effectiveBreakDurationSec=null,this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.clearFirstFrame("Break aborted before first frame"),this.audioFocus=null)}resolveChainedSuccessor(e){return this.breakSequenceDriver.resolveChainedSuccessor(e)}advanceToChainedBreak(e,t){this.breakSequenceDriver.advanceToChainedBreak(e,t)}preloadChainedSuccessor(e){this.preloader.preloadChainedSuccessor(e)}revealFirstFrame(){this.assetPlayback.revealFirstFrame()}armAdStartBudget(e){this.preloader.armAdStartBudget(e)}remainingAdStartBudgetMs(){return this.preloader.remainingAdStartBudgetMs()}loadWithinBudget(e,t){return this.preloader.loadWithinBudget(e,t)}async waitForFirstFrame(){return this.preloader.waitForFirstFrame()}clearFirstFrame(e="Break ended before first frame"){this.preloader.clearFirstFrame(e)}show(){this.adStage.show()}hide(){this.adStage.hide()}isAdPlaying(){return this.isPlaying}get muted(){return"content"===this.audioFocus?this.contentPlayer.muted:"ad"===this.audioFocus?this.adPlayer?this.adPlayer.muted:this.contentPlayer.muted:this.isPlaying&&this.adPlayer?this.adPlayer.muted:this.contentPlayer.muted}set muted(e){if("content"===this.audioFocus)this.contentPlayer.muted=e;else if("ad"===this.audioFocus)this.adPlayer&&(this.adPlayer.muted=e);else{(this.isPlaying&&this.adPlayer?this.adPlayer:this.contentPlayer).muted=e}this.vastAdManager?.setMuted(e),this.notifyVolumeChange()}get volume(){return"content"===this.audioFocus?this.contentPlayer.volume:"ad"===this.audioFocus?this.adPlayer?this.adPlayer.volume:this.contentPlayer.volume:this.isPlaying&&this.adPlayer?this.adPlayer.volume:this.contentPlayer.volume}set volume(e){if("content"===this.audioFocus)this.contentPlayer.volume=e;else if("ad"===this.audioFocus)this.adPlayer&&(this.adPlayer.volume=e);else{(this.isPlaying&&this.adPlayer?this.adPlayer:this.contentPlayer).volume=e}this.vastAdManager?.setVolume(e),this.notifyVolumeChange()}setVolumeChangeCallback(e){this.volumeChangeCallback=e}notifyVolumeChange(){this.volumeChangeCallback?.(this.muted,this.volume)}destroy(){if(this.destroyed)return;if(this.resumeGeneration++,g(this.state),this.successorQueue.reset(),!this.sharedElementPlayer.beginSharedActivity())return;this.destroyed=!0,this.adStage.destroy(),this.resumeCoordinator.cancelResumeLandedProbe(),this.resumeCoordinator.dispose(),this.resumeCoordinator.endResumeCatchup(),this.resumeCoordinator.endContinueContentPlayout(),this.state.resumePrepositionSettle&&(clearTimeout(this.state.resumePrepositionSettle),this.state.resumePrepositionSettle=null),this.releaseContentHold(),this.clearContentGate(),this.clearFirstFrame("Controller destroyed before first frame"),this.firstFrameGateActive=!1,this.firstFrameGateShown=!1,this.resetGamPodTracking(),I(this.state),this.companionRemoveTimer&&(clearTimeout(this.companionRemoveTimer),this.companionRemoveTimer=null),this.adFadeTimer&&(clearTimeout(this.adFadeTimer),this.adFadeTimer=null),this.adPlayer?.pause(),this.clearOverlayImage(),this.pauseAdPresenter.destroy(),this.contentVolumeHandler&&(this.contentPlayer.off("volumechange",this.contentVolumeHandler),this.contentVolumeHandler=null),this.sharedElementPlayer.detachSharedAdListeners(),this.sharedElementPlayer.releaseContentElementAdPlayer(),this.state.pipTransferredToAd=!1,this.teardownFullscreenTracking(),this.teardownPictureInPictureTracking(),this.adVolumeChangeHandler&&this.adPlayer&&this.adPlayer.off("volumechange",this.adVolumeChangeHandler),this.adVolumeChangeHandler=null,this.hide(),this.adStage.destroy(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.contentVideoMutationObserver?.disconnect(),this.contentVideoMutationObserver=null,this.contentVideoElement&&this.contentVideoGeometryHandler&&(this.contentVideoElement.removeEventListener("loadedmetadata",this.contentVideoGeometryHandler),this.contentVideoElement.removeEventListener("resize",this.contentVideoGeometryHandler)),this.contentVideoElement=null,this.contentVideoGeometryHandler=null;const e=this.adStage.restoreContent(this.playerContainerCreatedBySDK,this.playerContainerOriginalStyle);this.companionElement&&this.companionElement.parentElement&&(this.companionElement.parentElement.removeChild(this.companionElement),this.companionElement=null),this.isPlaying=!1,this.currentBreak=null,this.adContainer&&this.adContainer.parentElement&&this.adContainer.parentElement.removeChild(this.adContainer),!e&&this.stage&&this.stage.parentElement&&this.stage.parentElement.removeChild(this.stage),this.stage=null,this.adContainer=null,this.adMediaContainer=null;try{this.adPlayer?.destroy()}catch(e){this.log("Ad player adapter destroy failed (ignored):",e)}this.adPlayer=null,this.callbacks=null,this.gamPodBridge.destroy(),this.vastAdManager?.destroy(),this.vastAdManager=null,this.log("Ad player destroyed")}log(...e){this.debug&&u("[OptiViewAds:AdPlayerController]",...e)}}AdPlayerController.AD_START_BUDGET_MS=5e3,AdPlayerController.GAM_POD_AD_START_BUDGET_MS=1e4,AdPlayerController.MIN_AD_START_BUDGET_MS=3e3;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Break } from '../types/BreakManifest';
|
|
2
|
+
import type { TrackedBreak } from './RewindRearm';
|
|
3
|
+
/**
|
|
4
|
+
* The active break's chained successor appeared, changed or (`null`) disappeared after a
|
|
5
|
+
* manifest update. The renderer re-prepares or drops what it buffered for the switch.
|
|
6
|
+
*/
|
|
7
|
+
export type ChainSuccessorChangedCallback = (activeBreak: Break, successor: Break | null) => void;
|
|
8
|
+
export interface BreakChainDeps {
|
|
9
|
+
breaks: Map<string, TrackedBreak>;
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
maxGapMs: number;
|
|
12
|
+
toleranceMs: number;
|
|
13
|
+
getBreakStartTime: (breakInfo: Break) => number | null;
|
|
14
|
+
log: (...args: unknown[]) => void;
|
|
15
|
+
}
|
|
16
|
+
/** What a renderer buffers for a successor; two breaks with the same signature play the same media. */
|
|
17
|
+
export declare function chainSuccessorSignature(breakInfo: Break): string;
|
|
18
|
+
/**
|
|
19
|
+
* Back-to-back breaks played as one chain: the successors within the chaining gap are CHAINED so
|
|
20
|
+
* the time-based check never starts them on its own, and a manifest update while a break is
|
|
21
|
+
* active re-walks the chain, so a break announced during the chain joins it at once.
|
|
22
|
+
*/
|
|
23
|
+
export declare class BreakChain {
|
|
24
|
+
private readonly deps;
|
|
25
|
+
private onSuccessorChanged;
|
|
26
|
+
/** The successor last seen for the active break; a later manifest update is compared to it. */
|
|
27
|
+
private successorSeen;
|
|
28
|
+
constructor(deps: BreakChainDeps);
|
|
29
|
+
setOnSuccessorChanged(callback: ChainSuccessorChangedCallback | null): void;
|
|
30
|
+
/** Mark every PENDING break that chains after `breakId` as CHAINED. */
|
|
31
|
+
claim(breakId: string): void;
|
|
32
|
+
/** The PENDING/CHAINED break starting within the chaining gap after this break's end, or null. */
|
|
33
|
+
successorOf(breakId: string): Break | null;
|
|
34
|
+
/** Promote a CHAINED (or PENDING) break to ACTIVE as the chain advances into it. */
|
|
35
|
+
activate(breakId: string): void;
|
|
36
|
+
/** After a manifest update: re-walk the chain from the active break and report a changed successor. */
|
|
37
|
+
refresh(active: Break): void;
|
|
38
|
+
private rememberSuccessor;
|
|
39
|
+
/** Claim the breaks now in the chain; release a CHAINED break that moved out of it. */
|
|
40
|
+
private reclaim;
|
|
41
|
+
/** Earliest break starting within the chaining gap after `current`, restricted to `states`. */
|
|
42
|
+
private findSuccessor;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{BreakState as e}from"./BreakSchedulerTypes";import{variantsOf as s}from"./selectVariant";function t(e){const s=e.uri;return void 0===s?null:"string"==typeof s?s:s.map(e=>e.value)}export function chainSuccessorSignature(e){return JSON.stringify([e.id,e.start,e.duration,s(e).map(e=>[e.format,e.assets.map(e=>[e.id,e.type,t(e),e.duration??null])])])}export class BreakChain{constructor(e){this.deps=e,this.onSuccessorChanged=null,this.successorSeen=null}setOnSuccessorChanged(e){this.onSuccessorChanged=e}claim(s){if(!this.deps.enabled)return;let t=this.deps.breaks.get(s)?.break??null;for(;t;){const s=this.findSuccessor(t,[e.PENDING]);if(!s)break;const i=this.deps.breaks.get(s.id);if(!i||i.state!==e.PENDING)break;i.state=e.CHAINED,this.deps.log(`🔗 Break "${s.id}" claimed as chained after "${t.id}"`),t=s}this.rememberSuccessor(s)}successorOf(s){if(!this.deps.enabled)return null;const t=this.deps.breaks.get(s)?.break;return t?this.findSuccessor(t,[e.PENDING,e.CHAINED]):null}activate(s){const t=this.deps.breaks.get(s);t&&(t.state=e.ACTIVE,this.rememberSuccessor(s))}refresh(e){if(!this.deps.enabled)return;null!==this.deps.getBreakStartTime(e)&&this.reclaim(e);const s=this.successorOf(e.id),t=s?chainSuccessorSignature(s):null,i=this.successorSeen;this.successorSeen={activeId:e.id,signature:t},i?.activeId===e.id&&i.signature!==t&&(this.deps.log(`🔗 Successor of "${e.id}" is now ${s?`"${s.id}"`:"none"}`),this.onSuccessorChanged?.(e,s))}rememberSuccessor(e){const s=this.successorOf(e);this.successorSeen={activeId:e,signature:s?chainSuccessorSignature(s):null}}reclaim(s){const t=new Set;let i=s;for(;i;){const s=this.findSuccessor(i,[e.PENDING,e.CHAINED]);if(!s||t.has(s.id))break;t.add(s.id),i=s}for(const[i,r]of this.deps.breaks)t.has(i)&&r.state===e.PENDING?(r.state=e.CHAINED,this.deps.log(`🔗 Break "${i}" claimed as chained during "${s.id}"`)):t.has(i)||r.state!==e.CHAINED||(r.state=e.PENDING,this.deps.log(`Break "${i}" left the chain of "${s.id}"`))}findSuccessor(e,s){const t=this.deps.getBreakStartTime(e);if(null===t)return null;const i=t+1e3*(e.duration??0);let r=null;for(const n of this.deps.breaks.values()){if(n.break.id===e.id)continue;if(!s.includes(n.state))continue;const a=this.deps.getBreakStartTime(n.break);if(null===a)continue;if(a<=t)continue;const c=a-i;c>this.deps.maxGapMs||(c<-this.deps.toleranceMs||(!r||a<r.start)&&(r={break:n.break,start:a}))}return r?.break??null}}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type Break } from '../types/BreakManifest';
|
|
2
|
+
import { type Clock } from './BreakSchedulerTypes';
|
|
3
|
+
import type { BreakSwitchPath, BreakTransitionMeasurement } from './BreakTransitionTimer';
|
|
4
|
+
/** One break of a chain in a `DA-BREAK-CHAIN` report. */
|
|
5
|
+
export interface ChainBreakEntry {
|
|
6
|
+
id: string;
|
|
7
|
+
/** The manifest `start` (wallclock ISO string or timebase seconds); absent for an event-triggered break. */
|
|
8
|
+
scheduledStart?: string | number;
|
|
9
|
+
plannedDurationSec: number;
|
|
10
|
+
beganAtMs: number;
|
|
11
|
+
endedAtMs?: number;
|
|
12
|
+
/** Seconds from its begin to its end, one decimal. */
|
|
13
|
+
playedSec?: number;
|
|
14
|
+
/** It joined the chain after the chain began (published, or moved into the gap, by a poll). */
|
|
15
|
+
announcedDuringChain: boolean;
|
|
16
|
+
/** How the switch into it went; absent for the chain's first break and when the switch was not measured. */
|
|
17
|
+
path?: BreakSwitchPath;
|
|
18
|
+
}
|
|
19
|
+
/** One measured switch between two breaks of a chain. */
|
|
20
|
+
export interface ChainSwitchEntry {
|
|
21
|
+
toBreakId: string;
|
|
22
|
+
gapMs: number;
|
|
23
|
+
path: BreakSwitchPath;
|
|
24
|
+
leadMs?: number;
|
|
25
|
+
}
|
|
26
|
+
/** The `DA-BREAK-CHAIN` summary of one chain, from its first break's begin to content again. */
|
|
27
|
+
export interface BreakChainReport {
|
|
28
|
+
/** The chain's first break. */
|
|
29
|
+
chainId: string;
|
|
30
|
+
breaks: ChainBreakEntry[];
|
|
31
|
+
switches: ChainSwitchEntry[];
|
|
32
|
+
/** Milliseconds from the last break's end to content playing; absent when content did not resume. */
|
|
33
|
+
contentResumeMs?: number;
|
|
34
|
+
/** Milliseconds from the first break's begin to the last break's end. */
|
|
35
|
+
totalMs: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Collects one chain of breaks and reports it once, when content plays again or the chain is
|
|
39
|
+
* flushed (a new chain begins, the session ends). Fed by the SDK's break lifecycle and by the
|
|
40
|
+
* {@link BreakTransitionTimer} measurements; side-effect free with an injected clock.
|
|
41
|
+
*/
|
|
42
|
+
export declare class BreakChainRecorder {
|
|
43
|
+
private readonly onReport;
|
|
44
|
+
private readonly clock;
|
|
45
|
+
private breaks;
|
|
46
|
+
private switches;
|
|
47
|
+
private knownSuccessorId;
|
|
48
|
+
private announced;
|
|
49
|
+
/** The last break ended; the chain continues only if a chained break begins next. */
|
|
50
|
+
private lastEnded;
|
|
51
|
+
constructor(onReport: (report: BreakChainReport) => void, clock?: Clock);
|
|
52
|
+
/** A break began. A non-chained begin reports any open chain and starts a new one. */
|
|
53
|
+
breakBegan(breakInfo: Break, chained: boolean, knownSuccessorId: string | null): void;
|
|
54
|
+
/** The scheduler reported a new successor of the active break; a new id joined during the chain. */
|
|
55
|
+
successorChanged(successorId: string | null): void;
|
|
56
|
+
breakEnded(breakId: string): void;
|
|
57
|
+
/** A transition measurement: a switch into a chained break, or content playing after the chain. */
|
|
58
|
+
transitionMeasured(measurement: BreakTransitionMeasurement): void;
|
|
59
|
+
/** Report the open chain, if any, without a content resume time. */
|
|
60
|
+
flush(): void;
|
|
61
|
+
private entryFor;
|
|
62
|
+
private emit;
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isEventTrigger as s}from"../types/BreakManifest";import{systemClock as t}from"./BreakSchedulerTypes";export class BreakChainRecorder{constructor(s,e=t){this.onReport=s,this.clock=e,this.breaks=[],this.switches=[],this.knownSuccessorId=null,this.announced=new Set,this.lastEnded=!1}breakBegan(t,e,n){e||this.flush();const i=t.start;this.breaks.push({id:t.id,...s(i)?{}:{scheduledStart:i},plannedDurationSec:t.duration,beganAtMs:this.clock.now(),announcedDuringChain:e&&this.announced.has(t.id)}),this.knownSuccessorId=n,this.lastEnded=!1}successorChanged(s){this.breaks.length>0&&null!==s&&s!==this.knownSuccessorId&&this.announced.add(s),this.knownSuccessorId=s}breakEnded(s){const t=this.entryFor(s);if(!t||void 0!==t.endedAtMs)return;const e=this.clock.now();t.endedAtMs=e,t.playedSec=Math.round(Math.max(0,e-t.beganAtMs)/100)/10,this.lastEnded=!0}transitionMeasured(s){if("break-to-break"===s.kind){const t=this.entryFor(s.breakId);if(!t)return;const e=s.path??"cold";t.path=e,this.switches.push({toBreakId:s.breakId,gapMs:s.durationMs,path:e,...void 0!==s.leadMs?{leadMs:s.leadMs}:{}})}else"out-of-break"===s.kind&&this.lastEnded&&this.emit(s.durationMs)}flush(){this.breaks.length>0&&this.emit(void 0)}entryFor(s){for(let t=this.breaks.length-1;t>=0;t--)if(this.breaks[t].id===s)return this.breaks[t]}emit(s){const t=this.breaks[0],e=this.breaks[this.breaks.length-1].endedAtMs??this.clock.now(),n={chainId:t.id,breaks:this.breaks,switches:this.switches,...void 0!==s?{contentResumeMs:s}:{},totalMs:Math.max(0,e-t.beganAtMs)};this.breaks=[],this.switches=[],this.knownSuccessorId=null,this.announced=new Set,this.lastEnded=!1,this.onReport(n)}}
|