@@ -2390,11 +2390,13 @@ export class PlaylistController extends videojs.EventTarget {
2390
2390
* has no keyId leave it enabled by default.
2391
2391
*/
2392
2392
excludeNonUsablePlaylistsByKeyId_ ( ) {
2393
-
2394
2393
if ( ! this . mainPlaylistLoader_ || ! this . mainPlaylistLoader_ . main ) {
2395
2394
return ;
2396
2395
}
2397
2396
2397
+ let nonUsableKeyStatusCount = 0 ;
2398
+ const NON_USABLE = 'non-usable' ;
2399
+
2398
2400
this . mainPlaylistLoader_ . main . playlists . forEach ( ( playlist ) => {
2399
2401
const keyIdSet = this . mainPlaylistLoader_ . getKeyIdSet ( playlist ) ;
2400
2402
@@ -2404,21 +2406,39 @@ export class PlaylistController extends videojs.EventTarget {
2404
2406
}
2405
2407
keyIdSet . forEach ( ( key ) => {
2406
2408
const USABLE = 'usable' ;
2407
- const NON_USABLE = 'non-usable' ;
2408
2409
const hasUsableKeyStatus = this . keyStatusMap_ . has ( key ) && this . keyStatusMap_ . get ( key ) === USABLE ;
2409
2410
const nonUsableExclusion = playlist . lastExcludeReason_ === NON_USABLE && playlist . excludeUntil === Infinity ;
2410
2411
2411
2412
if ( ! hasUsableKeyStatus ) {
2412
- playlist . excludeUntil = Infinity ;
2413
- playlist . lastExcludeReason_ = NON_USABLE ;
2414
- this . logger_ ( `excluding playlist ${ playlist . id } because the key ID ${ key } doesn't exist in the keyStatusMap or is not ${ USABLE } ` ) ;
2413
+ // Only exclude playlists that haven't already been excluded as non-usable.
2414
+ if ( playlist . excludeUntil !== Infinity && playlist . lastExcludeReason_ !== NON_USABLE ) {
2415
+ playlist . excludeUntil = Infinity ;
2416
+ playlist . lastExcludeReason_ = NON_USABLE ;
2417
+ this . logger_ ( `excluding playlist ${ playlist . id } because the key ID ${ key } doesn't exist in the keyStatusMap or is not ${ USABLE } ` ) ;
2418
+ }
2419
+ // count all nonUsableKeyStatus
2420
+ nonUsableKeyStatusCount ++ ;
2415
2421
} else if ( hasUsableKeyStatus && nonUsableExclusion ) {
2416
2422
delete playlist . excludeUntil ;
2417
2423
delete playlist . lastExcludeReason_ ;
2418
2424
this . logger_ ( `enabling playlist ${ playlist . id } because key ID ${ key } is ${ USABLE } ` ) ;
2419
2425
}
2420
2426
} ) ;
2421
2427
} ) ;
2428
+
2429
+ // If for whatever reason every playlist has a non usable key status. Lets try re-including the SD renditions as a failsafe.
2430
+ if ( nonUsableKeyStatusCount >= this . mainPlaylistLoader_ . main . playlists . length ) {
2431
+ this . mainPlaylistLoader_ . main . playlists . forEach ( ( playlist ) => {
2432
+ const isNonHD = playlist && playlist . attributes && playlist . attributes . RESOLUTION && playlist . attributes . RESOLUTION . height < 720 ;
2433
+ const excludedForNonUsableKey = playlist . excludeUntil === Infinity && playlist . lastExcludeReason_ === NON_USABLE ;
2434
+
2435
+ if ( isNonHD && excludedForNonUsableKey ) {
2436
+ // Only delete the excludeUntil so we don't try and re-exclude these playlists.
2437
+ delete playlist . excludeUntil ;
2438
+ videojs . log . warn ( `enabling non-HD playlist ${ playlist . id } because all playlists were excluded due to ${ NON_USABLE } key IDs` ) ;
2439
+ }
2440
+ } ) ;
2441
+ }
2422
2442
}
2423
2443
2424
2444
/**
@@ -2430,9 +2450,10 @@ export class PlaylistController extends videojs.EventTarget {
2430
2450
addKeyStatus_ ( keyId , status ) {
2431
2451
const isString = typeof keyId === 'string' ;
2432
2452
const keyIdHexString = isString ? keyId : bufferToHexString ( keyId ) ;
2453
+ const formattedKeyIdString = keyIdHexString . slice ( 0 , 32 ) . toLowerCase ( ) ;
2433
2454
2434
- // 32 digit keyId hex string.
2435
- this . keyStatusMap_ . set ( keyIdHexString . slice ( 0 , 32 ) , status ) ;
2455
+ this . logger_ ( `KeyStatus ' ${ status } ' with key ID ${ formattedKeyIdString } added to the keyStatusMap` ) ;
2456
+ this . keyStatusMap_ . set ( formattedKeyIdString , status ) ;
2436
2457
}
2437
2458
2438
2459
/**
@@ -2443,6 +2464,15 @@ export class PlaylistController extends videojs.EventTarget {
2443
2464
*/
2444
2465
updatePlaylistByKeyStatus ( keyId , status ) {
2445
2466
this . addKeyStatus_ ( keyId , status ) ;
2467
+ if ( ! this . waitingForFastQualityPlaylistReceived_ ) {
2468
+ this . excludeNonUsableThenChangePlaylist_ ( ) ;
2469
+ }
2470
+ // Listen to loadedplaylist with a single listener and check for new contentProtection elements when a playlist is updated.
2471
+ this . mainPlaylistLoader_ . off ( 'loadedplaylist' , this . excludeNonUsableThenChangePlaylist_ . bind ( this ) ) ;
2472
+ this . mainPlaylistLoader_ . on ( 'loadedplaylist' , this . excludeNonUsableThenChangePlaylist_ . bind ( this ) ) ;
2473
+ }
2474
+
2475
+ excludeNonUsableThenChangePlaylist_ ( ) {
2446
2476
this . excludeNonUsablePlaylistsByKeyId_ ( ) ;
2447
2477
this . fastQualityChange_ ( ) ;
2448
2478
}
0 commit comments