@@ -83,14 +83,16 @@ class EMEController extends EventHandler {
8383 private _widevineLicenseUrl ?: string ;
8484 private _licenseXhrSetup ?: ( xhr : XMLHttpRequest , url : string ) => void ;
8585 private _emeEnabled : boolean ;
86- private _requestMediaKeySystemAccess : MediaKeyFunc | null
86+ private _requestMediaKeySystemAccess : MediaKeyFunc | null ;
8787
8888 private _config : EMEControllerConfig ;
8989 private _mediaKeysList : MediaKeysListItem [ ] = [ ] ;
9090 private _media : HTMLMediaElement | null = null ;
9191 private _hasSetMediaKeys : boolean = false ;
9292 private _requestLicenseFailureCount : number = 0 ;
9393
94+ private mediaKeysPromise : Promise < MediaKeys > | null = null ;
95+
9496 /**
9597 * @constructs
9698 * @param {Hls } hls Our Hls.js instance
@@ -143,13 +145,14 @@ class EMEController extends EventHandler {
143145 logger . log ( 'Requesting encrypted media key-system access' ) ;
144146
145147 // expecting interface like window.navigator.requestMediaKeySystemAccess
146- this . requestMediaKeySystemAccess ( keySystem , mediaKeySystemConfigs )
147- . then ( ( mediaKeySystemAccess ) => {
148- this . _onMediaKeySystemAccessObtained ( keySystem , mediaKeySystemAccess ) ;
149- } )
150- . catch ( ( err ) => {
151- logger . error ( `Failed to obtain key-system "${ keySystem } " access:` , err ) ;
152- } ) ;
148+ const keySystemAccessPromise = this . requestMediaKeySystemAccess ( keySystem , mediaKeySystemConfigs ) ;
149+
150+ this . mediaKeysPromise = keySystemAccessPromise . then ( ( mediaKeySystemAccess ) =>
151+ this . _onMediaKeySystemAccessObtained ( keySystem , mediaKeySystemAccess ) ) ;
152+
153+ keySystemAccessPromise . catch ( ( err ) => {
154+ logger . error ( `Failed to obtain key-system "${ keySystem } " access:` , err ) ;
155+ } ) ;
153156 }
154157
155158 get requestMediaKeySystemAccess ( ) {
@@ -166,7 +169,7 @@ class EMEController extends EventHandler {
166169 * @param {string } keySystem
167170 * @param {MediaKeySystemAccess } mediaKeySystemAccess https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemAccess
168171 */
169- private _onMediaKeySystemAccessObtained ( keySystem : KeySystems , mediaKeySystemAccess : MediaKeySystemAccess ) {
172+ private _onMediaKeySystemAccessObtained ( keySystem : KeySystems , mediaKeySystemAccess : MediaKeySystemAccess ) : Promise < MediaKeys > {
170173 logger . log ( `Access for key-system "${ keySystem } " obtained` ) ;
171174
172175 const mediaKeysListItem : MediaKeysListItem = {
@@ -177,17 +180,22 @@ class EMEController extends EventHandler {
177180
178181 this . _mediaKeysList . push ( mediaKeysListItem ) ;
179182
180- mediaKeySystemAccess . createMediaKeys ( )
183+ const mediaKeysPromise = Promise . resolve ( ) . then ( ( ) => mediaKeySystemAccess . createMediaKeys ( ) )
181184 . then ( ( mediaKeys ) => {
182185 mediaKeysListItem . mediaKeys = mediaKeys ;
183186
184187 logger . log ( `Media-keys created for key-system "${ keySystem } "` ) ;
185188
186189 this . _onMediaKeysCreated ( ) ;
187- } )
188- . catch ( ( err ) => {
189- logger . error ( 'Failed to create media-keys:' , err ) ;
190+
191+ return mediaKeys ;
190192 } ) ;
193+
194+ mediaKeysPromise . catch ( ( err ) => {
195+ logger . error ( 'Failed to create media-keys:' , err ) ;
196+ } ) ;
197+
198+ return mediaKeysPromise ;
191199 }
192200
193201 /**
@@ -235,20 +243,37 @@ class EMEController extends EventHandler {
235243
236244 /**
237245 * @private
238- * @param {string } initDataType
239- * @param {ArrayBuffer|null } initData
246+ * @param e {MediaEncryptedEvent}
240247 */
241248 private _onMediaEncrypted = ( e : MediaEncryptedEvent ) => {
242249 logger . log ( `Media is encrypted using "${ e . initDataType } " init data type` ) ;
243250
244- this . _attemptSetMediaKeys ( ) ;
245- this . _generateRequestWithPreferredKeySession ( e . initDataType , e . initData ) ;
251+ if ( ! this . mediaKeysPromise ) {
252+ logger . error ( 'Fatal: Media is encrypted but no CDM access or no keys have been requested' ) ;
253+ this . hls . trigger ( Event . ERROR , {
254+ type : ErrorTypes . KEY_SYSTEM_ERROR ,
255+ details : ErrorDetails . KEY_SYSTEM_NO_KEYS ,
256+ fatal : true
257+ } ) ;
258+ return ;
259+ }
260+
261+ const finallySetKeyAndStartSession = ( mediaKeys ) => {
262+ if ( ! this . _media ) {
263+ return ;
264+ }
265+ this . _attemptSetMediaKeys ( mediaKeys ) ;
266+ this . _generateRequestWithPreferredKeySession ( e . initDataType , e . initData ) ;
267+ } ;
268+
269+ // Could use `Promise.finally` but some Promise polyfills are missing it
270+ this . mediaKeysPromise . then ( finallySetKeyAndStartSession ) . catch ( finallySetKeyAndStartSession ) ;
246271 }
247272
248273 /**
249274 * @private
250275 */
251- private _attemptSetMediaKeys ( ) {
276+ private _attemptSetMediaKeys ( mediaKeys ?: MediaKeys ) {
252277 if ( ! this . _media ) {
253278 throw new Error ( 'Attempted to set mediaKeys without first attaching a media element' ) ;
254279 }
0 commit comments