mirror of
https://github.com/flutter/packages.git
synced 2025-06-30 14:47:22 +08:00
[video_player] fix: add missing isPlaybackLikelyToKeepUp check. (#3826)
When watching a live stream, if the playback buffers but the AVPlayerItem is likely to keep up, it is necessary to recheck AVPlayerItem.isPlaybackLikelyToKeepUp. If isPlaybackLikelyToKeepUp, a bufferingEnd event should be immediately triggered. I am encountering an issue with my product where, when watching a live stream, if I seek to the latest time, it continuously `bufferingStart` and does not come to an `bufferingEnd`.
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
## 2.4.8
|
||||
|
||||
* Fixes missing `isPlaybackLikelyToKeepUp` check for iOS video player `bufferingEnd` event and `bufferingStart` event.
|
||||
|
||||
## 2.4.7
|
||||
|
||||
* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18.
|
||||
|
@ -207,6 +207,52 @@
|
||||
[self waitForExpectationsWithTimeout:30.0 handler:nil];
|
||||
}
|
||||
|
||||
- (void)testBufferingStateFromPlayer {
|
||||
NSObject<FlutterPluginRegistry> *registry =
|
||||
(NSObject<FlutterPluginRegistry> *)[[UIApplication sharedApplication] delegate];
|
||||
NSObject<FlutterPluginRegistrar> *registrar =
|
||||
[registry registrarForPlugin:@"testLiveStreamBufferEndFromPlayer"];
|
||||
FLTVideoPlayerPlugin *videoPlayerPlugin =
|
||||
(FLTVideoPlayerPlugin *)[[FLTVideoPlayerPlugin alloc] initWithRegistrar:registrar];
|
||||
|
||||
FlutterError *error;
|
||||
[videoPlayerPlugin initialize:&error];
|
||||
XCTAssertNil(error);
|
||||
|
||||
FLTCreateMessage *create = [FLTCreateMessage
|
||||
makeWithAsset:nil
|
||||
uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4"
|
||||
packageName:nil
|
||||
formatHint:nil
|
||||
httpHeaders:@{}];
|
||||
FLTTextureMessage *textureMessage = [videoPlayerPlugin create:create error:&error];
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(textureMessage);
|
||||
FLTVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureMessage.textureId];
|
||||
XCTAssertNotNil(player);
|
||||
AVPlayer *avPlayer = player.player;
|
||||
[avPlayer play];
|
||||
|
||||
[player onListenWithArguments:nil
|
||||
eventSink:^(NSDictionary<NSString *, id> *event) {
|
||||
if ([event[@"event"] isEqualToString:@"bufferingEnd"]) {
|
||||
XCTAssertTrue(avPlayer.currentItem.isPlaybackLikelyToKeepUp);
|
||||
}
|
||||
|
||||
if ([event[@"event"] isEqualToString:@"bufferingStart"]) {
|
||||
XCTAssertFalse(avPlayer.currentItem.isPlaybackLikelyToKeepUp);
|
||||
}
|
||||
}];
|
||||
XCTestExpectation *bufferingStateExpectation =
|
||||
[self expectationWithDescription:@"bufferingState"];
|
||||
NSTimeInterval timeout = 10;
|
||||
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC);
|
||||
dispatch_after(delay, dispatch_get_main_queue(), ^{
|
||||
[bufferingStateExpectation fulfill];
|
||||
});
|
||||
[self waitForExpectationsWithTimeout:timeout + 1 handler:nil];
|
||||
}
|
||||
|
||||
- (void)testVideoControls {
|
||||
NSObject<FlutterPluginRegistry> *registry =
|
||||
(NSObject<FlutterPluginRegistry> *)[[UIApplication sharedApplication] delegate];
|
||||
|
@ -72,8 +72,6 @@ static void *statusContext = &statusContext;
|
||||
static void *presentationSizeContext = &presentationSizeContext;
|
||||
static void *durationContext = &durationContext;
|
||||
static void *playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext;
|
||||
static void *playbackBufferEmptyContext = &playbackBufferEmptyContext;
|
||||
static void *playbackBufferFullContext = &playbackBufferFullContext;
|
||||
static void *rateContext = &rateContext;
|
||||
|
||||
@implementation FLTVideoPlayer
|
||||
@ -108,14 +106,6 @@ static void *rateContext = &rateContext;
|
||||
forKeyPath:@"playbackLikelyToKeepUp"
|
||||
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
|
||||
context:playbackLikelyToKeepUpContext];
|
||||
[item addObserver:self
|
||||
forKeyPath:@"playbackBufferEmpty"
|
||||
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
|
||||
context:playbackBufferEmptyContext];
|
||||
[item addObserver:self
|
||||
forKeyPath:@"playbackBufferFull"
|
||||
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
|
||||
context:playbackBufferFullContext];
|
||||
|
||||
// Add observer to AVPlayer instead of AVPlayerItem since the AVPlayerItem does not have a "rate"
|
||||
// property
|
||||
@ -330,19 +320,15 @@ NS_INLINE UIViewController *rootViewController(void) {
|
||||
[self updatePlayingState];
|
||||
}
|
||||
} else if (context == playbackLikelyToKeepUpContext) {
|
||||
[self updatePlayingState];
|
||||
if ([[_player currentItem] isPlaybackLikelyToKeepUp]) {
|
||||
[self updatePlayingState];
|
||||
if (_eventSink != nil) {
|
||||
_eventSink(@{@"event" : @"bufferingEnd"});
|
||||
}
|
||||
}
|
||||
} else if (context == playbackBufferEmptyContext) {
|
||||
if (_eventSink != nil) {
|
||||
_eventSink(@{@"event" : @"bufferingStart"});
|
||||
}
|
||||
} else if (context == playbackBufferFullContext) {
|
||||
if (_eventSink != nil) {
|
||||
_eventSink(@{@"event" : @"bufferingEnd"});
|
||||
} else {
|
||||
if (_eventSink != nil) {
|
||||
_eventSink(@{@"event" : @"bufferingStart"});
|
||||
}
|
||||
}
|
||||
} else if (context == rateContext) {
|
||||
// Important: Make sure to cast the object to AVPlayer when observing the rate property,
|
||||
@ -528,8 +514,6 @@ NS_INLINE UIViewController *rootViewController(void) {
|
||||
[currentItem removeObserver:self forKeyPath:@"presentationSize"];
|
||||
[currentItem removeObserver:self forKeyPath:@"duration"];
|
||||
[currentItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
|
||||
[currentItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
|
||||
[currentItem removeObserver:self forKeyPath:@"playbackBufferFull"];
|
||||
|
||||
[self.player replaceCurrentItemWithPlayerItem:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
@ -2,7 +2,7 @@ name: video_player_avfoundation
|
||||
description: iOS implementation of the video_player plugin.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
|
||||
version: 2.4.7
|
||||
version: 2.4.8
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.0 <4.0.0"
|
||||
|
Reference in New Issue
Block a user