Skip to content

Commit

Permalink
Merge branch 'main' into fix/setState-returning-future
Browse files Browse the repository at this point in the history
  • Loading branch information
berhili098 authored Jan 15, 2025
2 parents 1868631 + 6d98122 commit f69c503
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .ci/flutter_stable.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
17025dd88227cd9532c33fa78f5250d548d87e9a
68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
4 changes: 4 additions & 0 deletions packages/video_player/video_player_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.6.7

* Fixes playback speed resetting.

## 2.6.6

* Fixes changing global audio session category to be collision free across plugins.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ - (void)testSeekToleranceWhenSeekingToEnd {
// Change playback speed.
[videoPlayerPlugin setPlaybackSpeed:2 forPlayer:textureId.integerValue error:&error];
XCTAssertNil(error);
[videoPlayerPlugin playPlayer:textureId.integerValue error:&error];
XCTAssertNil(error);
XCTAssertEqual(avPlayer.rate, 2);
XCTAssertEqual(avPlayer.timeControlStatus, AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate);

Expand Down Expand Up @@ -839,6 +841,41 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent {
[self waitForExpectationsWithTimeout:10.0 handler:nil];
}

- (void)testUpdatePlayingStateShouldNotResetRate {
NSObject<FlutterPluginRegistrar> *registrar =
[GetPluginRegistry() registrarForPlugin:@"testUpdatePlayingStateShouldNotResetRate"];

FVPVideoPlayerPlugin *videoPlayerPlugin = [[FVPVideoPlayerPlugin alloc]
initWithAVFactory:[[StubFVPAVFactory alloc] initWithPlayer:nil output:nil]
displayLinkFactory:nil
registrar:registrar];

FlutterError *error;
[videoPlayerPlugin initialize:&error];
XCTAssertNil(error);
FVPCreationOptions *create = [FVPCreationOptions
makeWithAsset:nil
uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4"
packageName:nil
formatHint:nil
httpHeaders:@{}];
NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error];
FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId];

XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"];
[player onListenWithArguments:nil
eventSink:^(NSDictionary<NSString *, id> *event) {
if ([event[@"event"] isEqualToString:@"initialized"]) {
[initializedExpectation fulfill];
}
}];
[self waitForExpectationsWithTimeout:10 handler:nil];

[videoPlayerPlugin setPlaybackSpeed:2 forPlayer:textureId.integerValue error:&error];
[videoPlayerPlugin playPlayer:textureId.integerValue error:&error];
XCTAssertEqual(player.player.rate, 2);
}

#if TARGET_OS_IOS
- (void)testVideoPlayerShouldNotOverwritePlayAndRecordNorDefaultToSpeaker {
NSObject<FlutterPluginRegistrar> *registrar = [GetPluginRegistry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ @interface FVPVideoPlayer ()
@property(nonatomic) CGAffineTransform preferredTransform;
/// Indicates whether the video player is currently playing.
@property(nonatomic, readonly) BOOL isPlaying;
/// The target playback speed requested by the plugin client.
@property(nonatomic, readonly) NSNumber *targetPlaybackSpeed;
/// Indicates whether the video player has been initialized.
@property(nonatomic, readonly) BOOL isInitialized;
/// The updater that drives callbacks to the engine to indicate that a new frame is ready.
Expand Down Expand Up @@ -323,7 +325,15 @@ - (void)updatePlayingState {
return;
}
if (_isPlaying) {
[_player play];
// Calling play is the same as setting the rate to 1.0 (or to defaultRate depending on iOS
// version) so last set playback speed must be set here if any instead.
// https://github.com/flutter/flutter/issues/71264
// https://github.com/flutter/flutter/issues/73643
if (_targetPlaybackSpeed) {
[self updateRate];
} else {
[_player play];
}
} else {
[_player pause];
}
Expand All @@ -332,6 +342,32 @@ - (void)updatePlayingState {
_displayLink.running = _isPlaying || self.waitingForFrame;
}

/// Synchronizes the player's playback rate with targetPlaybackSpeed, constrained by the playback
/// rate capabilities of the player's current item.
- (void)updateRate {
// See https://developer.apple.com/library/archive/qa/qa1772/_index.html for an explanation of
// these checks.
// If status is not AVPlayerItemStatusReadyToPlay then both canPlayFastForward
// and canPlaySlowForward are always false and it is unknown whether video can
// be played at these speeds, updatePlayingState will be called again when
// status changes to AVPlayerItemStatusReadyToPlay.
float speed = _targetPlaybackSpeed.floatValue;
BOOL readyToPlay = _player.currentItem.status == AVPlayerItemStatusReadyToPlay;
if (speed > 2.0 && !_player.currentItem.canPlayFastForward) {
if (!readyToPlay) {
return;
}
speed = 2.0;
}
if (speed < 1.0 && !_player.currentItem.canPlaySlowForward) {
if (!readyToPlay) {
return;
}
speed = 1.0;
}
_player.rate = speed;
}

- (void)sendFailedToLoadVideoEvent {
if (_eventSink == nil) {
return;
Expand Down Expand Up @@ -473,27 +509,8 @@ - (void)setVolume:(double)volume {
}

- (void)setPlaybackSpeed:(double)speed {
// See https://developer.apple.com/library/archive/qa/qa1772/_index.html for an explanation of
// these checks.
if (speed > 2.0 && !_player.currentItem.canPlayFastForward) {
if (_eventSink != nil) {
_eventSink([FlutterError errorWithCode:@"VideoError"
message:@"Video cannot be fast-forwarded beyond 2.0x"
details:nil]);
}
return;
}

if (speed < 1.0 && !_player.currentItem.canPlaySlowForward) {
if (_eventSink != nil) {
_eventSink([FlutterError errorWithCode:@"VideoError"
message:@"Video cannot be slow-forwarded"
details:nil]);
}
return;
}

_player.rate = speed;
_targetPlaybackSpeed = @(speed);
[self updatePlayingState];
}

- (CVPixelBufferRef)copyPixelBuffer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: video_player_avfoundation
description: iOS and macOS 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.6.6
version: 2.6.7

environment:
sdk: ^3.4.0
Expand Down

0 comments on commit f69c503

Please sign in to comment.