-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[video_player_avfoundation] fix playback speed resetting #7657
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 2.6.3 | ||
|
||
* Fixes playback speed resetting. | ||
|
||
## 2.6.2 | ||
|
||
* Updates Pigeon for non-nullable collection type support. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,6 +82,8 @@ @interface FVPVideoPlayer () | |
@property(nonatomic) CGAffineTransform preferredTransform; | ||
@property(nonatomic, readonly) BOOL disposed; | ||
@property(nonatomic, readonly) BOOL isPlaying; | ||
// Playback speed when video is playing. | ||
@property(nonatomic, readonly) NSNumber *playbackSpeed; | ||
@property(nonatomic) BOOL isLooping; | ||
@property(nonatomic, readonly) BOOL isInitialized; | ||
// The updater that drives callbacks to the engine to indicate that a new frame is ready. | ||
|
@@ -397,7 +399,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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: 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 (_playbackSpeed) { | ||
[self updateRate]; | ||
} else { | ||
[_player play]; | ||
stuartmorgan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} else { | ||
[_player pause]; | ||
} | ||
|
@@ -406,6 +416,30 @@ - (void)updatePlayingState { | |
_displayLink.running = _isPlaying || self.waitingForFrame; | ||
} | ||
|
||
- (void)updateRate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a declaration comment, per the style guide. |
||
// 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 = _playbackSpeed.floatValue; | ||
bool readyToPlay = _player.currentItem.status == AVPlayerItemStatusReadyToPlay; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
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)setupEventSinkIfReadyToPlay { | ||
if (_eventSink && !_isInitialized) { | ||
AVPlayerItem *currentItem = self.player.currentItem; | ||
|
@@ -519,27 +553,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; | ||
_playbackSpeed = @(speed); | ||
[self updatePlayingState]; | ||
} | ||
|
||
- (CVPixelBufferRef)copyPixelBuffer { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be more accurate to call this
targetPlaybackSpeed
(and document it as something like "The target playback speed requested by the plugin client."), since it's entirely possible for the playback speed to not be this value while playing.