From f69f79e5f214880eaaabbbb8e70d698d627d22b0 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Sat, 26 Mar 2022 23:30:58 +0800 Subject: [PATCH 01/11] Apply the correct transform for videos with different orientations --- .../video_player_avfoundation/CHANGELOG.md | 4 + .../ios/RunnerTests/VideoPlayerTests.m | 93 +++++++++++++++++++ .../ios/Classes/AVAssetTrack+Utils.h | 15 +++ .../ios/Classes/AVAssetTrack+Utils.m | 48 ++++++++++ .../ios/Classes/FLTVideoPlayerPlugin.m | 26 +----- .../video_player_avfoundation/pubspec.yaml | 2 +- 6 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h create mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index c36c9878d1a1..3b393c05addf 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.2 + +* Apply the correct transform for videos with different orientations. + ## 2.3.1 * Renames internal method channels to avoid potential confusion with the diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m index cbf2866aa071..8f1598b67492 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m @@ -7,6 +7,7 @@ @import XCTest; #import +#import @interface FLTVideoPlayer : NSObject @property(readonly, nonatomic) AVPlayer *player; @@ -17,6 +18,44 @@ @interface FLTVideoPlayerPlugin (Test) NSMutableDictionary *playersByTextureId; @end +@interface FakeAVAssetTrack : AVAssetTrack +@property(readonly, nonatomic) CGAffineTransform preferredTransform; +@property(readonly, nonatomic) CGSize naturalSize; +@property(readonly, nonatomic) UIImageOrientation orientation; +- (instancetype)initWithOrientation:(UIImageOrientation)orientation; +@end + +@implementation FakeAVAssetTrack + +- (instancetype)initWithOrientation:(UIImageOrientation)orientation { + _orientation = orientation; + _naturalSize = CGSizeMake(800, 600); + return self; +} + +- (CGAffineTransform)preferredTransform { + switch (_orientation) { + case UIImageOrientationUp: + return CGAffineTransformMake(1, 0, 0, 1, 0, 0); + case UIImageOrientationDown: + return CGAffineTransformMake(-1, 0, 0, -1, 0, 0); + case UIImageOrientationLeft: + return CGAffineTransformMake(0, -1, 1, 0, 0, 0); + case UIImageOrientationRight: + return CGAffineTransformMake(0, 1, -1, 0, 0, 0); + case UIImageOrientationUpMirrored: + return CGAffineTransformMake(-1, 0, 0, 1, 0, 0); + case UIImageOrientationDownMirrored: + return CGAffineTransformMake(1, 0, 0, -1, 0, 0); + case UIImageOrientationLeftMirrored: + return CGAffineTransformMake(0, -1, -1, 0, 0, 0); + case UIImageOrientationRightMirrored: + return CGAffineTransformMake(0, 1, 1, 0, 0, 0); + } +} + +@end + @interface VideoPlayerTests : XCTestCase @end @@ -121,6 +160,17 @@ - (void)testHLSControls { XCTAssertEqualWithAccuracy([videoInitialization[@"duration"] intValue], 4000, 200); } +- (void)testTransformFix { + [self testTransformFixByOrientation:UIImageOrientationUp]; + [self testTransformFixByOrientation:UIImageOrientationDown]; + [self testTransformFixByOrientation:UIImageOrientationLeft]; + [self testTransformFixByOrientation:UIImageOrientationRight]; + [self testTransformFixByOrientation:UIImageOrientationUpMirrored]; + [self testTransformFixByOrientation:UIImageOrientationDownMirrored]; + [self testTransformFixByOrientation:UIImageOrientationLeftMirrored]; + [self testTransformFixByOrientation:UIImageOrientationRightMirrored]; +} + - (NSDictionary *)testPlugin:(FLTVideoPlayerPlugin *)videoPlayerPlugin uri:(NSString *)uri { FlutterError *error; @@ -175,4 +225,47 @@ - (void)testHLSControls { return initializationEvent; } +- (void)testTransformFixByOrientation:(UIImageOrientation)orientation { + AVAssetTrack *track = [[FakeAVAssetTrack alloc] initWithOrientation:orientation]; + CGAffineTransform t = [track fixTransform]; + CGSize size = track.naturalSize; + CGFloat expectX, expectY; + switch (orientation) { + case UIImageOrientationUp: + expectX = 0; + expectY = 0; + break; + case UIImageOrientationDown: + expectX = size.width; + expectY = size.height; + break; + case UIImageOrientationLeft: + expectX = 0; + expectY = size.width; + break; + case UIImageOrientationRight: + expectX = size.height; + expectY = 0; + break; + case UIImageOrientationUpMirrored: + expectX = size.width; + expectY = 0; + break; + case UIImageOrientationDownMirrored: + expectX = 0; + expectY = size.height; + break; + case UIImageOrientationLeftMirrored: + expectX = size.height; + expectY = size.width; + break; + case UIImageOrientationRightMirrored: + expectX = 0; + expectY = 0; + break; + } + XCTAssertEqual(t.tx, expectX); + XCTAssertEqual(t.ty, expectY); +} + @end diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h new file mode 100644 index 000000000000..8dcbde685f34 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Fix the transform for the track. +// Each fix case corresponding to `UIImage.Orientation`, with 8 cases in total. +@interface AVAssetTrack (Utils) +- (CGAffineTransform)fixTransform; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m new file mode 100644 index 000000000000..e34b3e8cd540 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m @@ -0,0 +1,48 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "AVAssetTrack+Utils.h" + +@implementation AVAssetTrack (Utils) + +- (CGAffineTransform)fixTransform { + CGAffineTransform t = self.preferredTransform; + CGSize size = self.naturalSize; + if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUp + t.tx = 0; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDown + t.tx = size.width; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == 1 && t.d == 0) { + // UIImageOrientationLeft + t.tx = 0; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == -1 && t.d == 0) { + // UIImageOrientationRight + t.tx = size.height; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUpMirrored + t.tx = size.width; + t.ty = 0; + } else if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDownMirrored + t.tx = 0; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == -1 && t.d == 0) { + // UIImageOrientationLeftMirrored + t.tx = size.height; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == 1 && t.d == 0) { + // UIImageOrientationRightMirrored + t.tx = 0; + t.ty = 0; + } + return t; +} + +@end diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index 2fb9f7f55600..3358271304c7 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -5,6 +5,7 @@ #import "FLTVideoPlayerPlugin.h" #import #import +#import "AVAssetTrack+Utils.h" #import "messages.g.h" #if !__has_feature(objc_arc) @@ -187,29 +188,6 @@ - (instancetype)initWithURL:(NSURL *)url return [self initWithPlayerItem:item frameUpdater:frameUpdater]; } -- (CGAffineTransform)fixTransform:(AVAssetTrack *)videoTrack { - CGAffineTransform transform = videoTrack.preferredTransform; - // TODO(@recastrodiaz): why do we need to do this? Why is the preferredTransform incorrect? - // At least 2 user videos show a black screen when in portrait mode if we directly use the - // videoTrack.preferredTransform Setting tx to the height of the video instead of 0, properly - // displays the video https://github.com/flutter/flutter/issues/17606#issuecomment-413473181 - if (transform.tx == 0 && transform.ty == 0) { - NSInteger rotationDegrees = (NSInteger)round(radiansToDegrees(atan2(transform.b, transform.a))); - NSLog(@"TX and TY are 0. Rotation: %ld. Natural width,height: %f, %f", (long)rotationDegrees, - videoTrack.naturalSize.width, videoTrack.naturalSize.height); - if (rotationDegrees == 90) { - NSLog(@"Setting transform tx"); - transform.tx = videoTrack.naturalSize.height; - transform.ty = 0; - } else if (rotationDegrees == 270) { - NSLog(@"Setting transform ty"); - transform.tx = 0; - transform.ty = videoTrack.naturalSize.width; - } - } - return transform; -} - - (instancetype)initWithPlayerItem:(AVPlayerItem *)item frameUpdater:(FLTFrameUpdater *)frameUpdater { self = [super init]; @@ -226,7 +204,7 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item if ([videoTrack statusOfValueForKey:@"preferredTransform" error:nil] == AVKeyValueStatusLoaded) { // Rotate the video by using a videoComposition and the preferredTransform - self->_preferredTransform = [self fixTransform:videoTrack]; + self->_preferredTransform = [videoTrack fixTransform]; // Note: // https://developer.apple.com/documentation/avfoundation/avplayeritem/1388818-videocomposition // Video composition can only be used with file-based media and is not supported for diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 0e42c26de829..5874b52cba6f 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_avfoundation description: iOS implementation of the video_player plugin. repository: https://github.com/flutter/plugins/tree/master/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.3.1 +version: 2.3.2 environment: sdk: ">=2.14.0 <3.0.0" From 85da558e4c1bfa75eab6cb3826e8fb2ad1ad9b09 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 7 Apr 2022 23:24:58 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9C=85=20`testTransformFixByOrientatio?= =?UTF-8?q?n`=20->=20`validateTransformFixForOrientation`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/ios/RunnerTests/VideoPlayerTests.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m index 8f1598b67492..e127db6a0769 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m @@ -161,14 +161,14 @@ - (void)testHLSControls { } - (void)testTransformFix { - [self testTransformFixByOrientation:UIImageOrientationUp]; - [self testTransformFixByOrientation:UIImageOrientationDown]; - [self testTransformFixByOrientation:UIImageOrientationLeft]; - [self testTransformFixByOrientation:UIImageOrientationRight]; - [self testTransformFixByOrientation:UIImageOrientationUpMirrored]; - [self testTransformFixByOrientation:UIImageOrientationDownMirrored]; - [self testTransformFixByOrientation:UIImageOrientationLeftMirrored]; - [self testTransformFixByOrientation:UIImageOrientationRightMirrored]; + [self validateTransformFixForOrientation:UIImageOrientationUp]; + [self validateTransformFixForOrientation:UIImageOrientationDown]; + [self validateTransformFixForOrientation:UIImageOrientationLeft]; + [self validateTransformFixForOrientation:UIImageOrientationRight]; + [self validateTransformFixForOrientation:UIImageOrientationUpMirrored]; + [self validateTransformFixForOrientation:UIImageOrientationDownMirrored]; + [self validateTransformFixForOrientation:UIImageOrientationLeftMirrored]; + [self validateTransformFixForOrientation:UIImageOrientationRightMirrored]; } - (NSDictionary *)testPlugin:(FLTVideoPlayerPlugin *)videoPlayerPlugin @@ -225,7 +225,7 @@ - (void)testTransformFix { return initializationEvent; } -- (void)testTransformFixByOrientation:(UIImageOrientation)orientation { +- (void)validateTransformFixForOrientation:(UIImageOrientation)orientation { AVAssetTrack *track = [[FakeAVAssetTrack alloc] initWithOrientation:orientation]; CGAffineTransform t = [track fixTransform]; CGSize size = track.naturalSize; From bc4b06de49b18d594f3984794301d60c7df8b1cf Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 7 Apr 2022 23:25:18 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=8E=A8=20Extra=20blank=20lines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ios/Classes/FLTVideoPlayerPlugin.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index 3358271304c7..ee067b6fb00a 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -3,8 +3,10 @@ // found in the LICENSE file. #import "FLTVideoPlayerPlugin.h" + #import #import + #import "AVAssetTrack+Utils.h" #import "messages.g.h" From 7a74c2ad106b38543153f0b4639cdb52ede32966 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 7 Apr 2022 23:25:44 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=F0=9F=92=A1=20Rewrite=20and=20move=20aro?= =?UTF-8?q?und=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ios/Classes/AVAssetTrack+Utils.h | 10 ++++++++-- .../ios/Classes/AVAssetTrack+Utils.m | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h index 8dcbde685f34..46020ded16b1 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h @@ -6,10 +6,16 @@ NS_ASSUME_NONNULL_BEGIN -// Fix the transform for the track. -// Each fix case corresponding to `UIImage.Orientation`, with 8 cases in total. @interface AVAssetTrack (Utils) + +/** + * Note: https://stackoverflow.com/questions/64161544 + * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` + * on iOS 14 and above. This method provide a corrected transform + * according to the orientation state of the track. + */ - (CGAffineTransform)fixTransform; + @end NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m index e34b3e8cd540..fe6c1b52bbb5 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m @@ -6,6 +6,8 @@ @implementation AVAssetTrack (Utils) +// Each case of control flows corresponding to +// a specific `UIImageOrientation`, with 8 cases in total. - (CGAffineTransform)fixTransform { CGAffineTransform t = self.preferredTransform; CGSize size = self.naturalSize; From 2ae271b391ddef1f6c4d0c8db836dab0d27952b8 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 8 Apr 2022 00:19:45 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rewrite=20the=20cate?= =?UTF-8?q?gory=20as=20a=20C=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ios/RunnerTests/VideoPlayerTests.m | 3 +- .../ios/Classes/AVAssetTrack+Utils.h | 21 -------- .../ios/Classes/AVAssetTrack+Utils.m | 50 ------------------- .../ios/Classes/FLTVideoPlayerPlugin.m | 50 ++++++++++++++++++- 4 files changed, 49 insertions(+), 75 deletions(-) delete mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h delete mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m index e127db6a0769..f59607137619 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m @@ -7,7 +7,6 @@ @import XCTest; #import -#import @interface FLTVideoPlayer : NSObject @property(readonly, nonatomic) AVPlayer *player; @@ -227,7 +226,7 @@ - (void)testTransformFix { - (void)validateTransformFixForOrientation:(UIImageOrientation)orientation { AVAssetTrack *track = [[FakeAVAssetTrack alloc] initWithOrientation:orientation]; - CGAffineTransform t = [track fixTransform]; + CGAffineTransform t = FLTGetStandardizedTransformForTrack(track); CGSize size = track.naturalSize; CGFloat expectX, expectY; switch (orientation) { diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h deleted file mode 100644 index 46020ded16b1..000000000000 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface AVAssetTrack (Utils) - -/** - * Note: https://stackoverflow.com/questions/64161544 - * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` - * on iOS 14 and above. This method provide a corrected transform - * according to the orientation state of the track. - */ -- (CGAffineTransform)fixTransform; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m deleted file mode 100644 index fe6c1b52bbb5..000000000000 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrack+Utils.m +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "AVAssetTrack+Utils.h" - -@implementation AVAssetTrack (Utils) - -// Each case of control flows corresponding to -// a specific `UIImageOrientation`, with 8 cases in total. -- (CGAffineTransform)fixTransform { - CGAffineTransform t = self.preferredTransform; - CGSize size = self.naturalSize; - if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == 1) { - // UIImageOrientationUp - t.tx = 0; - t.ty = 0; - } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == -1) { - // UIImageOrientationDown - t.tx = size.width; - t.ty = size.height; - } else if (t.a == 0 && t.b == -1 && t.c == 1 && t.d == 0) { - // UIImageOrientationLeft - t.tx = 0; - t.ty = size.width; - } else if (t.a == 0 && t.b == 1 && t.c == -1 && t.d == 0) { - // UIImageOrientationRight - t.tx = size.height; - t.ty = 0; - } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == 1) { - // UIImageOrientationUpMirrored - t.tx = size.width; - t.ty = 0; - } else if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == -1) { - // UIImageOrientationDownMirrored - t.tx = 0; - t.ty = size.height; - } else if (t.a == 0 && t.b == -1 && t.c == -1 && t.d == 0) { - // UIImageOrientationLeftMirrored - t.tx = size.height; - t.ty = size.width; - } else if (t.a == 0 && t.b == 1 && t.c == 1 && t.d == 0) { - // UIImageOrientationRightMirrored - t.tx = 0; - t.ty = 0; - } - return t; -} - -@end diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index ee067b6fb00a..b6bde290ca26 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -7,13 +7,59 @@ #import #import -#import "AVAssetTrack+Utils.h" #import "messages.g.h" #if !__has_feature(objc_arc) #error Code Requires ARC. #endif +/** + * Note: https://stackoverflow.com/questions/64161544 + * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` + * on iOS 14 and above. This method provide a corrected transform + * according to the orientation state of the track. + */ +static CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track) { + CGAffineTransform t = track.preferredTransform; + CGSize size = track.naturalSize; + // Each case of control flows corresponding to + // a specific `UIImageOrientation`, with 8 cases in total. + if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUp + t.tx = 0; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDown + t.tx = size.width; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == 1 && t.d == 0) { + // UIImageOrientationLeft + t.tx = 0; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == -1 && t.d == 0) { + // UIImageOrientationRight + t.tx = size.height; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUpMirrored + t.tx = size.width; + t.ty = 0; + } else if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDownMirrored + t.tx = 0; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == -1 && t.d == 0) { + // UIImageOrientationLeftMirrored + t.tx = size.height; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == 1 && t.d == 0) { + // UIImageOrientationRightMirrored + t.tx = 0; + t.ty = 0; + } + return t; +} + @interface FLTFrameUpdater : NSObject @property(nonatomic) int64_t textureId; @property(nonatomic, weak, readonly) NSObject *registry; @@ -206,7 +252,7 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item if ([videoTrack statusOfValueForKey:@"preferredTransform" error:nil] == AVKeyValueStatusLoaded) { // Rotate the video by using a videoComposition and the preferredTransform - self->_preferredTransform = [videoTrack fixTransform]; + self->_preferredTransform = FLTGetStandardizedTransformForTrack(videoTrack); // Note: // https://developer.apple.com/documentation/avfoundation/avplayeritem/1388818-videocomposition // Video composition can only be used with file-based media and is not supported for From 7c91a3f9c9f6cf8bcdd42840231392af471be277 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 8 Apr 2022 00:26:40 +0800 Subject: [PATCH 06/11] Apply suggestions from code review --- .../ios/Classes/FLTVideoPlayerPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index b6bde290ca26..6c493742b28e 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -16,8 +16,8 @@ /** * Note: https://stackoverflow.com/questions/64161544 * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` - * on iOS 14 and above. This method provide a corrected transform - * according to the orientation state of the track. + * on iOS 14 and above. This method provide a standardized transform + * according to the orientation of the track. */ static CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track) { CGAffineTransform t = track.preferredTransform; From 1c7bc9a412ab0fa29605934ad0fec43798c50cfa Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 8 Apr 2022 10:35:20 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rewrite=20the=20cate?= =?UTF-8?q?gory=20as=20a=20C=20function=20x2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ios/RunnerTests/VideoPlayerTests.m | 1 + .../ios/Classes/AVAssetTrackUtils.h | 13 +++++ .../ios/Classes/AVAssetTrackUtils.m | 46 ++++++++++++++++++ .../ios/Classes/FLTVideoPlayerPlugin.m | 48 +------------------ 4 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h create mode 100644 packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.m diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m index f59607137619..7decd04bd168 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerTests/VideoPlayerTests.m @@ -7,6 +7,7 @@ @import XCTest; #import +#import @interface FLTVideoPlayer : NSObject @property(readonly, nonatomic) AVPlayer *player; diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h new file mode 100644 index 000000000000..d6f193de0eda --- /dev/null +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h @@ -0,0 +1,13 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +/** + * Note: https://stackoverflow.com/questions/64161544 + * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` + * on iOS 14 and above. This function provides a standardized transform + * according to the orientation of the track. + */ +CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track); diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.m b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.m new file mode 100644 index 000000000000..de75859a94a4 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.m @@ -0,0 +1,46 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track) { + CGAffineTransform t = track.preferredTransform; + CGSize size = track.naturalSize; + // Each case of control flows corresponds to a specific + // `UIImageOrientation`, with 8 cases in total. + if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUp + t.tx = 0; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDown + t.tx = size.width; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == 1 && t.d == 0) { + // UIImageOrientationLeft + t.tx = 0; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == -1 && t.d == 0) { + // UIImageOrientationRight + t.tx = size.height; + t.ty = 0; + } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == 1) { + // UIImageOrientationUpMirrored + t.tx = size.width; + t.ty = 0; + } else if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == -1) { + // UIImageOrientationDownMirrored + t.tx = 0; + t.ty = size.height; + } else if (t.a == 0 && t.b == -1 && t.c == -1 && t.d == 0) { + // UIImageOrientationLeftMirrored + t.tx = size.height; + t.ty = size.width; + } else if (t.a == 0 && t.b == 1 && t.c == 1 && t.d == 0) { + // UIImageOrientationRightMirrored + t.tx = 0; + t.ty = 0; + } + return t; +} diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index 6c493742b28e..686dcf403962 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "AVAssetTrackUtils.h" #import "FLTVideoPlayerPlugin.h" #import @@ -13,53 +14,6 @@ #error Code Requires ARC. #endif -/** - * Note: https://stackoverflow.com/questions/64161544 - * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` - * on iOS 14 and above. This method provide a standardized transform - * according to the orientation of the track. - */ -static CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track) { - CGAffineTransform t = track.preferredTransform; - CGSize size = track.naturalSize; - // Each case of control flows corresponding to - // a specific `UIImageOrientation`, with 8 cases in total. - if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == 1) { - // UIImageOrientationUp - t.tx = 0; - t.ty = 0; - } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == -1) { - // UIImageOrientationDown - t.tx = size.width; - t.ty = size.height; - } else if (t.a == 0 && t.b == -1 && t.c == 1 && t.d == 0) { - // UIImageOrientationLeft - t.tx = 0; - t.ty = size.width; - } else if (t.a == 0 && t.b == 1 && t.c == -1 && t.d == 0) { - // UIImageOrientationRight - t.tx = size.height; - t.ty = 0; - } else if (t.a == -1 && t.b == 0 && t.c == 0 && t.d == 1) { - // UIImageOrientationUpMirrored - t.tx = size.width; - t.ty = 0; - } else if (t.a == 1 && t.b == 0 && t.c == 0 && t.d == -1) { - // UIImageOrientationDownMirrored - t.tx = 0; - t.ty = size.height; - } else if (t.a == 0 && t.b == -1 && t.c == -1 && t.d == 0) { - // UIImageOrientationLeftMirrored - t.tx = size.height; - t.ty = size.width; - } else if (t.a == 0 && t.b == 1 && t.c == 1 && t.d == 0) { - // UIImageOrientationRightMirrored - t.tx = 0; - t.ty = 0; - } - return t; -} - @interface FLTFrameUpdater : NSObject @property(nonatomic) int64_t textureId; @property(nonatomic, weak, readonly) NSObject *registry; From 2bb2f41b3b4c752b7b88d607f8b814ae89ee6e53 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 8 Apr 2022 10:38:16 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=8E=A8=20Format=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h | 2 +- .../ios/Classes/FLTVideoPlayerPlugin.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h index d6f193de0eda..589cb08738cf 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h @@ -10,4 +10,4 @@ * on iOS 14 and above. This function provides a standardized transform * according to the orientation of the track. */ -CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack *track); +CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack* track); diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index 686dcf403962..39d9e38efc3b 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "AVAssetTrackUtils.h" #import "FLTVideoPlayerPlugin.h" +#import "AVAssetTrackUtils.h" #import #import From e452c89b92c9c20a625f82be0ed3a04b5c040c53 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 8 Apr 2022 17:26:44 +0800 Subject: [PATCH 09/11] Apply suggestions from code review --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 3b393c05addf..3408158321a3 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.3.2 -* Apply the correct transform for videos with different orientations. +* Apply the standardized transform for videos with different orientations. ## 2.3.1 From 07cb30e77b0e1286ca8bfca5907f6066d0ef8e67 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 13 Apr 2022 11:56:11 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=92=A1=20Remove=20the=20comment=20a?= =?UTF-8?q?bout=20iOS=2014+?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h index 589cb08738cf..86e1c3e3b1af 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h @@ -6,8 +6,8 @@ /** * Note: https://stackoverflow.com/questions/64161544 - * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty` - * on iOS 14 and above. This function provides a standardized transform + * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty`. + * This function provides a standardized transform * according to the orientation of the track. */ CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack* track); From b801da1fa0cdae0288411003b36af057e92813c8 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Tue, 19 Apr 2022 11:30:08 +0800 Subject: [PATCH 11/11] Apply suggestions from code review --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 2 +- .../ios/Classes/AVAssetTrackUtils.h | 5 +++-- .../ios/Classes/FLTVideoPlayerPlugin.m | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 3408158321a3..a1f23eb670fc 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.3.2 -* Apply the standardized transform for videos with different orientations. +* Applies the standardized transform for videos with different orientations. ## 2.3.1 diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h index 86e1c3e3b1af..9d736bc21afe 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h +++ b/packages/video_player/video_player_avfoundation/ios/Classes/AVAssetTrackUtils.h @@ -5,9 +5,10 @@ #import /** + * Returns a standardized transform + * according to the orientation of the track. + * * Note: https://stackoverflow.com/questions/64161544 * `AVAssetTrack.preferredTransform` can have wrong `tx` and `ty`. - * This function provides a standardized transform - * according to the orientation of the track. */ CGAffineTransform FLTGetStandardizedTransformForTrack(AVAssetTrack* track); diff --git a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m index 39d9e38efc3b..a95779b1cbab 100644 --- a/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m @@ -3,11 +3,11 @@ // found in the LICENSE file. #import "FLTVideoPlayerPlugin.h" -#import "AVAssetTrackUtils.h" #import #import +#import "AVAssetTrackUtils.h" #import "messages.g.h" #if !__has_feature(objc_arc)