@@ -19,20 +19,18 @@ type RestrictedLevel = { width: number; height: number; bitrate: number };
19
19
class CapLevelController implements ComponentAPI {
20
20
private hls : Hls ;
21
21
private autoLevelCapping : number ;
22
- private firstLevel : number ;
23
22
private media : HTMLVideoElement | null ;
24
23
private restrictedLevels : RestrictedLevel [ ] ;
25
- private timer : number | undefined ;
24
+ private timer ?: number ;
25
+ private observer ?: ResizeObserver ;
26
26
private clientRect : { width : number ; height : number } | null ;
27
27
private streamController ?: StreamController ;
28
28
29
29
constructor ( hls : Hls ) {
30
30
this . hls = hls ;
31
31
this . autoLevelCapping = Number . POSITIVE_INFINITY ;
32
- this . firstLevel = - 1 ;
33
32
this . media = null ;
34
33
this . restrictedLevels = [ ] ;
35
- this . timer = undefined ;
36
34
this . clientRect = null ;
37
35
38
36
this . registerListeners ( ) ;
@@ -46,7 +44,7 @@ class CapLevelController implements ComponentAPI {
46
44
if ( this . hls ) {
47
45
this . unregisterListener ( ) ;
48
46
}
49
- if ( this . timer ) {
47
+ if ( this . timer || this . observer ) {
50
48
this . stopCapping ( ) ;
51
49
}
52
50
this . media = null ;
@@ -94,9 +92,17 @@ class CapLevelController implements ComponentAPI {
94
92
event : Events . MEDIA_ATTACHING ,
95
93
data : MediaAttachingData ,
96
94
) {
97
- this . media = data . media instanceof HTMLVideoElement ? data . media : null ;
95
+ const media = data . media ;
98
96
this . clientRect = null ;
99
- if ( this . timer && this . hls . levels . length ) {
97
+ if ( media instanceof HTMLVideoElement ) {
98
+ this . media = media ;
99
+ if ( this . hls . config . capLevelToPlayerSize ) {
100
+ this . observe ( ) ;
101
+ }
102
+ } else {
103
+ this . media = null ;
104
+ }
105
+ if ( ( this . timer || this . observer ) && this . hls . levels . length ) {
100
106
this . detectPlayerSize ( ) ;
101
107
}
102
108
}
@@ -107,7 +113,6 @@ class CapLevelController implements ComponentAPI {
107
113
) {
108
114
const hls = this . hls ;
109
115
this . restrictedLevels = [ ] ;
110
- this . firstLevel = data . firstLevel ;
111
116
if ( hls . config . capLevelToPlayerSize && data . video ) {
112
117
// Start capping immediately if the manifest has signaled video codecs
113
118
this . startCapping ( ) ;
@@ -118,7 +123,10 @@ class CapLevelController implements ComponentAPI {
118
123
event : Events . LEVELS_UPDATED ,
119
124
data : LevelsUpdatedData ,
120
125
) {
121
- if ( this . timer && Number . isFinite ( this . autoLevelCapping ) ) {
126
+ if (
127
+ ( this . timer || this . observer ) &&
128
+ Number . isFinite ( this . autoLevelCapping )
129
+ ) {
122
130
this . detectPlayerSize ( ) ;
123
131
}
124
132
}
@@ -183,34 +191,58 @@ class CapLevelController implements ComponentAPI {
183
191
const validLevels = levels . filter (
184
192
( level , index ) => this . isLevelAllowed ( level ) && index <= capLevelIndex ,
185
193
) ;
186
-
187
- this . clientRect = null ;
194
+ if ( ! this . observer ) {
195
+ this . clientRect = null ;
196
+ }
188
197
return CapLevelController . getMaxLevelByMediaSize (
189
198
validLevels ,
190
199
this . mediaWidth ,
191
200
this . mediaHeight ,
192
201
) ;
193
202
}
194
203
204
+ private observe ( ) {
205
+ const ResizeObserver = self . ResizeObserver ;
206
+ if ( ResizeObserver ) {
207
+ this . observer = new ResizeObserver ( ( entries ) => {
208
+ const bounds = entries [ 0 ] ?. contentRect ;
209
+ if ( bounds ) {
210
+ this . clientRect = bounds ;
211
+ this . detectPlayerSize ( ) ;
212
+ }
213
+ } ) ;
214
+ }
215
+ if ( this . observer && this . media ) {
216
+ this . observer . observe ( this . media ) ;
217
+ }
218
+ }
219
+
195
220
startCapping ( ) {
196
- if ( this . timer ) {
221
+ if ( this . timer || this . observer ) {
197
222
// Don't reset capping if started twice; this can happen if the manifest signals a video codec
198
223
return ;
199
224
}
200
- this . autoLevelCapping = Number . POSITIVE_INFINITY ;
201
225
self . clearInterval ( this . timer ) ;
202
- this . timer = self . setInterval ( this . detectPlayerSize . bind ( this ) , 1000 ) ;
226
+ this . timer = undefined ;
227
+ this . autoLevelCapping = Number . POSITIVE_INFINITY ;
228
+ this . observe ( ) ;
229
+ if ( ! this . observer ) {
230
+ this . timer = self . setInterval ( this . detectPlayerSize . bind ( this ) , 1000 ) ;
231
+ }
203
232
this . detectPlayerSize ( ) ;
204
233
}
205
234
206
235
stopCapping ( ) {
207
236
this . restrictedLevels = [ ] ;
208
- this . firstLevel = - 1 ;
209
237
this . autoLevelCapping = Number . POSITIVE_INFINITY ;
210
238
if ( this . timer ) {
211
239
self . clearInterval ( this . timer ) ;
212
240
this . timer = undefined ;
213
241
}
242
+ if ( this . observer ) {
243
+ this . observer . disconnect ( ) ;
244
+ this . observer = undefined ;
245
+ }
214
246
}
215
247
216
248
getDimensions ( ) : { width : number ; height : number } {
0 commit comments