@@ -52,6 +52,8 @@ - (void)updatePlayingState;
52
52
53
53
static void * timeRangeContext = &timeRangeContext;
54
54
static void * statusContext = &statusContext;
55
+ static void * presentationSizeContext = &presentationSizeContext;
56
+ static void * durationContext = &durationContext;
55
57
static void * playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext;
56
58
static void * playbackBufferEmptyContext = &playbackBufferEmptyContext;
57
59
static void * playbackBufferFullContext = &playbackBufferFullContext;
@@ -71,6 +73,14 @@ - (void)addObservers:(AVPlayerItem*)item {
71
73
forKeyPath: @" status"
72
74
options: NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
73
75
context: statusContext];
76
+ [item addObserver: self
77
+ forKeyPath: @" presentationSize"
78
+ options: NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
79
+ context: presentationSizeContext];
80
+ [item addObserver: self
81
+ forKeyPath: @" duration"
82
+ options: NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
83
+ context: durationContext];
74
84
[item addObserver: self
75
85
forKeyPath: @" playbackLikelyToKeepUp"
76
86
options: NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
@@ -282,10 +292,19 @@ - (void)observeValueForKeyPath:(NSString*)path
282
292
break ;
283
293
case AVPlayerItemStatusReadyToPlay:
284
294
[item addOutput: _videoOutput];
285
- [self sendInitialized ];
295
+ [self setupEventSinkIfReadyToPlay ];
286
296
[self updatePlayingState ];
287
297
break ;
288
298
}
299
+ } else if (context == presentationSizeContext || context == durationContext) {
300
+ AVPlayerItem* item = (AVPlayerItem*)object;
301
+ if (item.status == AVPlayerItemStatusReadyToPlay) {
302
+ // Due to an apparent bug, when the player item is ready, it still may not have determined
303
+ // its presentation size or duration. When these properties are finally set, re-check if
304
+ // all required properties and instantiate the event sink if it is not already set up.
305
+ [self setupEventSinkIfReadyToPlay ];
306
+ [self updatePlayingState ];
307
+ }
289
308
} else if (context == playbackLikelyToKeepUpContext) {
290
309
if ([[_player currentItem ] isPlaybackLikelyToKeepUp ]) {
291
310
[self updatePlayingState ];
@@ -316,7 +335,7 @@ - (void)updatePlayingState {
316
335
_displayLink.paused = !_isPlaying;
317
336
}
318
337
319
- - (void )sendInitialized {
338
+ - (void )setupEventSinkIfReadyToPlay {
320
339
if (_eventSink && !_isInitialized) {
321
340
CGSize size = [self .player currentItem ].presentationSize ;
322
341
CGFloat width = size.width ;
@@ -425,7 +444,7 @@ - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
425
444
// This line ensures the 'initialized' event is sent when the event
426
445
// 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function
427
446
// onListenWithArguments is called)
428
- [self sendInitialized ];
447
+ [self setupEventSinkIfReadyToPlay ];
429
448
return nil ;
430
449
}
431
450
0 commit comments