Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7837ddb
Added setPlayBackSpeed method where provided speed at which video sho…
JONA-Cureambit Mar 26, 2019
8578587
Added setSpeed method which pass the value to videoplayer plugin
JONA-Cureambit Mar 26, 2019
30e30ab
Test cases for normal speed as well as for changed speed has been passed
JONA-Cureambit Mar 26, 2019
d65e7dc
CHANGEDLOG.md has been updated with appropriate message.
JONA-Cureambit Mar 26, 2019
2aebbf9
Merge remote-tracking branch 'jonac/master' into speed
recastrodiaz Apr 23, 2019
f8d3491
- Implemented playback speed feature on iOS
recastrodiaz Apr 23, 2019
87dc34d
Added setPlayBackSpeed method where provided speed at which video sho…
JONA-Cureambit Mar 26, 2019
9138402
Added setSpeed method which pass the value to videoplayer plugin
JONA-Cureambit Mar 26, 2019
bca9603
Test cases for normal speed as well as for changed speed has been passed
JONA-Cureambit Mar 26, 2019
8d16064
CHANGEDLOG.md has been updated with appropriate message.
JONA-Cureambit Mar 26, 2019
51f04f3
rebased and merged from upstream
JONA-Cureambit Apr 25, 2019
b2d6080
Merge branch 'master' into speed
JONA-Cureambit Apr 25, 2019
39d39cf
Merge pull request #1 from recastrodiaz/speed
JONA-Cureambit Apr 25, 2019
da322f5
Added setPlayBackSpeed method where provided speed at which video sho…
JONA-Cureambit Mar 26, 2019
aec50ac
Added setSpeed method which pass the value to videoplayer plugin
JONA-Cureambit Mar 26, 2019
1ed0ead
Test cases for normal speed as well as for changed speed has been passed
JONA-Cureambit Mar 26, 2019
ea77b8d
- Implemented playback speed feature on iOS
recastrodiaz Apr 23, 2019
432ad66
Merge commit 'b2d6080a7279a34c1a1ed0b3a549495200f85738' into video_pl…
JONA-Cureambit Apr 25, 2019
8bd85d8
Merge branch 'video_player_speed'
JONA-Cureambit Apr 25, 2019
968489d
Merge branch 'master' into master
JONA-Cureambit Apr 26, 2019
5583c6b
- setPlayBackSpeed renamed to setSpeed.
JONA-Cureambit May 27, 2019
52d537c
- setPlayBackSpeed renamed to setSpeed.
JONA-Cureambit May 27, 2019
3209ac0
Renamed setPlaybackSpeed to setSpeed on iOS
recastrodiaz May 27, 2019
1e7311d
CHANGELOG and pubspec file has been updated to 0.10.0+8 version
JONA-Cureambit May 27, 2019
0ad74cc
Merge branch 'master' into master
JONA-Cureambit May 27, 2019
b6a3522
Merge pull request #2 from recastrodiaz/speed
JONA-Cureambit May 27, 2019
86c1644
[video_player] add type params for invokeMethod calls.
axellebot Jul 19, 2019
e68b84c
Merge pull request #3 from axellebot/invokeMethod
JONA-Cureambit Aug 7, 2019
9696c9d
Merge branch 'master' into master
JONA-Cureambit Aug 7, 2019
7225730
Throw a FlutterError if the speed is unsupported in iOS.
recastrodiaz Aug 7, 2019
ebd97e9
- Improve documentation for supported speeds in video_player
recastrodiaz Aug 7, 2019
f48cccc
Format files
recastrodiaz Aug 8, 2019
6882ce4
Merge pull request #4 from recastrodiaz/speed
JONA-Cureambit Aug 12, 2019
c9a68a1
Update CHANGELOG.md
JONA-Cureambit Aug 12, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.10.1+7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be at least a major update? Bumping to 1.2.0 could introduce breaking changes, and it's new features should at least a minor. Should go towards 0.11.0


* Implemented playback speed feature.
* Bump the minimum Flutter version to 1.2.0.
* Add template type parameter to `invokeMethod` calls.

## 0.10.1+6

* [iOS] Fixed a memory leak with notification observing.
Expand Down Expand Up @@ -34,7 +40,6 @@

* Fix a few other IDE warnings.


## 0.10.0+7

* Android: Fix issue where buffering status in percentage instead of milliseconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.EventListener;
import com.google.android.exoplayer2.SimpleExoPlayer;
Expand Down Expand Up @@ -232,6 +233,14 @@ long getPosition() {
return exoPlayer.getCurrentPosition();
}

void setSpeed(double value) {
float bracketedValue = (float) value;
PlaybackParameters existingParam = exoPlayer.getPlaybackParameters();
PlaybackParameters newParameter =
new PlaybackParameters(bracketedValue, existingParam.pitch, existingParam.skipSilence);
exoPlayer.setPlaybackParameters(newParameter);
}

@SuppressWarnings("SuspiciousNameCombination")
private void sendInitialized() {
if (isInitialized) {
Expand Down Expand Up @@ -402,6 +411,10 @@ private void onMethodCall(MethodCall call, Result result, long textureId, VideoP
videoPlayers.remove(textureId);
result.success(null);
break;
case "setSpeed":
player.setSpeed((Double) call.argument("speed"));
result.success(null);
break;
default:
result.notImplemented();
break;
Expand Down
28 changes: 28 additions & 0 deletions packages/video_player/ios/Classes/VideoPlayerPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,31 @@ - (void)setVolume:(double)volume {
_player.volume = (float)((volume < 0.0) ? 0.0 : ((volume > 1.0) ? 1.0 : volume));
}

- (void)setSpeed:(double)speed result:(FlutterResult)result {
if (speed == 1.0 || speed == 0.0) {
_player.rate = speed;
result(nil);
} else if (speed < 0 || speed > 2.0) {
result([FlutterError errorWithCode:@"unsupported_speed"
message:@"Speed must be >= 0.0 and <= 2.0"
details:nil]);
} else if ((speed > 1.0 && _player.currentItem.canPlayFastForward) ||
(speed < 1.0 && _player.currentItem.canPlaySlowForward)) {
_player.rate = speed;
result(nil);
} else {
if (speed > 1.0) {
result([FlutterError errorWithCode:@"unsupported_fast_forward"
message:@"This video cannot be played fast forward"
details:nil]);
} else {
result([FlutterError errorWithCode:@"unsupported_slow_forward"
message:@"This video cannot be played slow forward"
details:nil]);
}
}
}

- (CVPixelBufferRef)copyPixelBuffer {
CMTime outputItemTime = [_videoOutput itemTimeForHostTime:CACurrentMediaTime()];
if ([_videoOutput hasNewPixelBufferForItemTime:outputItemTime]) {
Expand Down Expand Up @@ -506,6 +531,9 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
} else if ([@"pause" isEqualToString:call.method]) {
[player pause];
result(nil);
} else if ([@"setSpeed" isEqualToString:call.method]) {
[player setSpeed:[[argsMap objectForKey:@"speed"] doubleValue] result:result];
return;
} else {
result(FlutterMethodNotImplemented);
}
Expand Down
52 changes: 48 additions & 4 deletions packages/video_player/lib/video_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';

final MethodChannel _channel = const MethodChannel('flutter.io/videoPlayer')
// This will clear all open videos on the platform when a full restart is
// performed.
// This will clear all open videos on the platform when a full restart is
// performed.
..invokeMethod<void>('init');

class DurationRange {
Expand Down Expand Up @@ -45,6 +45,7 @@ class VideoPlayerValue {
this.isBuffering = false,
this.volume = 1.0,
this.errorDescription,
this.speed = 1.0,
});

VideoPlayerValue.uninitialized() : this(duration: null);
Expand Down Expand Up @@ -85,8 +86,13 @@ class VideoPlayerValue {
/// Is null when [initialized] is false.
final Size size;

///The Current speed of the playback.
final double speed;

bool get initialized => duration != null;

bool get hasError => errorDescription != null;

double get aspectRatio => size != null ? size.width / size.height : 1.0;

VideoPlayerValue copyWith({
Expand All @@ -99,6 +105,7 @@ class VideoPlayerValue {
bool isBuffering,
double volume,
String errorDescription,
double speed,
}) {
return VideoPlayerValue(
duration: duration ?? this.duration,
Expand All @@ -109,6 +116,7 @@ class VideoPlayerValue {
isLooping: isLooping ?? this.isLooping,
isBuffering: isBuffering ?? this.isBuffering,
volume: volume ?? this.volume,
speed: speed ?? this.speed,
errorDescription: errorDescription ?? this.errorDescription,
);
}
Expand All @@ -124,7 +132,8 @@ class VideoPlayerValue {
'isLooping: $isLooping, '
'isBuffering: $isBuffering'
'volume: $volume, '
'errorDescription: $errorDescription)';
'errorDescription: $errorDescription'
'speed: $speed)';
}
}

Expand Down Expand Up @@ -239,6 +248,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
_applyLooping();
_applyVolume();
_applyPlayPause();
_applySpeed();
break;
case 'completed':
value = value.copyWith(isPlaying: false, position: value.duration);
Expand Down Expand Up @@ -341,6 +351,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
value = value.copyWith(position: newPosition);
},
);

// Ensure the video is played at the correct speed
await _applySpeed();
} else {
_timer?.cancel();
await _channel.invokeMethod<void>(
Expand Down Expand Up @@ -397,6 +410,37 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
value = value.copyWith(volume: volume.clamp(0.0, 1.0));
await _applyVolume();
}

Future<void> _applySpeed() async {
if (!value.initialized || _isDisposed) {
return;
}

// On iOS setting the speed on an AVPlayer starts playing
// the video straightaway. We avoid this surprising behaviour
// by not changing the speed of the player until after the video
// starts playing
if (!value.isPlaying) {
return;
}

await _channel.invokeMethod<void>(
'setSpeed',
<String, dynamic>{'textureId': _textureId, 'speed': value.speed},
);
}

/// Sets the playback speed of [this].
///
/// [speed] can be 0.5x, 1x, 2x
/// by default speed value is 1.0
///
/// Negative speeds are not supported
/// speeds above 2x are not supported on iOS
Future<void> setSpeed(double speed) async {
value = value.copyWith(speed: speed);
await _applySpeed();
}
}

class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver {
Expand Down
4 changes: 2 additions & 2 deletions packages/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: video_player
description: Flutter plugin for displaying inline video with other Flutter
widgets on Android and iOS.
author: Flutter Team <[email protected]>
version: 0.10.1+6
version: 0.10.1+7
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player

flutter:
Expand All @@ -22,4 +22,4 @@ dev_dependencies:

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
flutter: ">=1.5.0 <2.0.0"
flutter: ">=1.2.0 <2.0.0"
19 changes: 19 additions & 0 deletions packages/video_player/test/video_player_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
Future<void> play() async {}
@override
Future<void> setLooping(bool looping) async {}
@override
Future<void> setSpeed(double speed) async {
value = value.copyWith(speed: speed);
}
}

void main() {
Expand Down Expand Up @@ -73,4 +77,19 @@ void main() {
),
findsOneWidget);
});

testWidgets('default playback speed', (WidgetTester tester) async {
final FakeController controller = FakeController();
controller.textureId = 101;
await tester.pumpWidget(VideoPlayer(controller));
expect(controller.value.speed, 1.0);
});

testWidgets('Changed playback speed', (WidgetTester tester) async {
final FakeController controller = FakeController();
controller.textureId = 101;
controller.setSpeed(1.5);
await tester.pumpWidget(VideoPlayer(controller));
expect(controller.value.speed, 1.5);
});
}