Skip to content

Commit

Permalink
[video_player] Initialize player when size and duration become availa…
Browse files Browse the repository at this point in the history
…ble (flutter#4438)
  • Loading branch information
jmagman authored Oct 27, 2021
1 parent bb62aaa commit 76e84c0
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 20 deletions.
4 changes: 4 additions & 0 deletions packages/video_player/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.2.6

* Initialize player when size and duration become available on iOS

## 2.2.5

* Support to closed caption WebVTT format added.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 50;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -269,7 +269,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1100;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "The Flutter Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1100"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,46 @@ - (void)setUp {
[self.app launch];
}

- (void)testTabs {
- (void)testPlayVideo {
XCUIApplication* app = self.app;

XCUIElement* remoteTab = [app.otherElements
elementMatchingPredicate:[NSPredicate predicateWithFormat:@"selected == YES"]];
if (![remoteTab waitForExistenceWithTimeout:30.0]) {
os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
XCTFail(@"Failed due to not able to find selected Remote tab");
}
XCTAssertTrue([remoteTab waitForExistenceWithTimeout:30.0]);
XCTAssertTrue([remoteTab.label containsString:@"Remote"]);

XCUIElement* playButton = app.staticTexts[@"Play"];
XCTAssertTrue([playButton waitForExistenceWithTimeout:30.0]);
[playButton tap];

XCUIElement* chirpClosedCaption = app.staticTexts[@"[ Birds chirping ]"];
XCTAssertTrue([chirpClosedCaption waitForExistenceWithTimeout:30.0]);

XCUIElement* buzzClosedCaption = app.staticTexts[@"[ Buzzing ]"];
XCTAssertTrue([buzzClosedCaption waitForExistenceWithTimeout:30.0]);

XCUIElement* playbackSpeed1x = app.staticTexts[@"Playback speed\n1.0x"];
XCTAssertTrue([playbackSpeed1x waitForExistenceWithTimeout:30.0]);
[playbackSpeed1x tap];

XCUIElement* playbackSpeed5xButton = app.buttons[@"5.0x"];
XCTAssertTrue([playbackSpeed5xButton waitForExistenceWithTimeout:30.0]);
[playbackSpeed5xButton tap];

XCUIElement* playbackSpeed5x = app.staticTexts[@"Playback speed\n5.0x"];
XCTAssertTrue([playbackSpeed5x waitForExistenceWithTimeout:30.0]);

// Cycle through tabs.
for (NSString* tabName in @[ @"Asset", @"List example" ]) {
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"label BEGINSWITH %@", tabName];
XCUIElement* unselectedTab = [app.staticTexts elementMatchingPredicate:predicate];
if (![unselectedTab waitForExistenceWithTimeout:30.0]) {
os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
XCTFail(@"Failed due to not able to find unselected %@ tab", tabName);
}
XCTAssertTrue([unselectedTab waitForExistenceWithTimeout:30.0]);
XCTAssertFalse(unselectedTab.isSelected);
[unselectedTab tap];

XCUIElement* selectedTab = [app.otherElements
elementMatchingPredicate:[NSPredicate predicateWithFormat:@"label BEGINSWITH %@", tabName]];
if (![selectedTab waitForExistenceWithTimeout:30.0]) {
os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
XCTFail(@"Failed due to not able to find selected %@ tab", tabName);
}
XCTAssertTrue([selectedTab waitForExistenceWithTimeout:30.0]);
XCTAssertTrue(selectedTab.isSelected);
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/video_player/video_player/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ class _ControlsOverlay extends StatelessWidget {
Icons.play_arrow,
color: Colors.white,
size: 100.0,
semanticLabel: 'Play',
),
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ - (void)updatePlayingState;

static void* timeRangeContext = &timeRangeContext;
static void* statusContext = &statusContext;
static void* presentationSizeContext = &presentationSizeContext;
static void* durationContext = &durationContext;
static void* playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext;
static void* playbackBufferEmptyContext = &playbackBufferEmptyContext;
static void* playbackBufferFullContext = &playbackBufferFullContext;
Expand All @@ -71,6 +73,14 @@ - (void)addObservers:(AVPlayerItem*)item {
forKeyPath:@"status"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:statusContext];
[item addObserver:self
forKeyPath:@"presentationSize"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:presentationSizeContext];
[item addObserver:self
forKeyPath:@"duration"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:durationContext];
[item addObserver:self
forKeyPath:@"playbackLikelyToKeepUp"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
Expand Down Expand Up @@ -282,10 +292,19 @@ - (void)observeValueForKeyPath:(NSString*)path
break;
case AVPlayerItemStatusReadyToPlay:
[item addOutput:_videoOutput];
[self sendInitialized];
[self setupEventSinkIfReadyToPlay];
[self updatePlayingState];
break;
}
} else if (context == presentationSizeContext || context == durationContext) {
AVPlayerItem* item = (AVPlayerItem*)object;
if (item.status == AVPlayerItemStatusReadyToPlay) {
// Due to an apparent bug, when the player item is ready, it still may not have determined
// its presentation size or duration. When these properties are finally set, re-check if
// all required properties and instantiate the event sink if it is not already set up.
[self setupEventSinkIfReadyToPlay];
[self updatePlayingState];
}
} else if (context == playbackLikelyToKeepUpContext) {
if ([[_player currentItem] isPlaybackLikelyToKeepUp]) {
[self updatePlayingState];
Expand Down Expand Up @@ -316,7 +335,7 @@ - (void)updatePlayingState {
_displayLink.paused = !_isPlaying;
}

- (void)sendInitialized {
- (void)setupEventSinkIfReadyToPlay {
if (_eventSink && !_isInitialized) {
CGSize size = [self.player currentItem].presentationSize;
CGFloat width = size.width;
Expand Down Expand Up @@ -425,7 +444,7 @@ - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
// This line ensures the 'initialized' event is sent when the event
// 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function
// onListenWithArguments is called)
[self sendInitialized];
[self setupEventSinkIfReadyToPlay];
return nil;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/video_player/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for displaying inline video with other Flutter
widgets on Android, iOS, and web.
repository: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
version: 2.2.5
version: 2.2.6

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down

0 comments on commit 76e84c0

Please sign in to comment.