Skip to content

Commit

Permalink
[video_player] Fixes a bug where the aspect ratio of some HLS videos …
Browse files Browse the repository at this point in the history
…are incorrectly inverted (#6507)
  • Loading branch information
hellohuanlin authored Oct 3, 2022
1 parent a295dc1 commit 25e10b2
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 41 deletions.
3 changes: 2 additions & 1 deletion packages/video_player/video_player_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.3.7

* Fixes a bug where the aspect ratio of some HLS videos are incorrectly inverted.
* Updates code for `no_leading_underscores_for_local_identifiers` lint.

## 2.3.6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@

@interface FLTVideoPlayer : NSObject <FlutterStreamHandler>
@property(readonly, nonatomic) AVPlayer *player;
// This is to fix a bug (https://github.com/flutter/flutter/issues/111457) in iOS 16 with blank
// video for encrypted video streams. An invisible AVPlayerLayer is used to overwrite the
// protection of pixel buffers in those streams.
@property(readonly, nonatomic) AVPlayerLayer *playerLayer;
@end

Expand Down Expand Up @@ -65,13 +62,12 @@ @interface VideoPlayerTests : XCTestCase

@implementation VideoPlayerTests

- (void)testIOS16BugWithEncryptedVideoStream {
// This is to fix a bug (https://github.com/flutter/flutter/issues/111457) in iOS 16 with blank
// video for encrypted video streams. An invisible AVPlayerLayer is used to overwrite the
// protection of pixel buffers in those streams.
// Note that a better unit test is to validate that `copyPixelBuffer` API returns the pixel
// buffers as expected, which requires setting up the video player properly with a protected video
// stream (.m3u8 file).
- (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSomeVideoStream {
// This is to fix 2 bugs: 1. blank video for encrypted video streams on iOS 16
// (https://github.com/flutter/flutter/issues/111457) and 2. swapped width and height for some
// video streams (not just iOS 16). (https://github.com/flutter/flutter/issues/109116). An
// invisible AVPlayerLayer is used to overwrite the protection of pixel buffers in those streams
// for issue #1, and restore the correct width and height for issue #2.
NSObject<FlutterPluginRegistry> *registry =
(NSObject<FlutterPluginRegistry> *)[[UIApplication sharedApplication] delegate];
NSObject<FlutterPluginRegistrar> *registrar =
Expand All @@ -95,13 +91,8 @@ - (void)testIOS16BugWithEncryptedVideoStream {
FLTVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureMessage.textureId];
XCTAssertNotNil(player);

if (@available(iOS 16.0, *)) {
XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present for iOS 16.");
XCTAssertNotNil(player.playerLayer.superlayer,
@"AVPlayerLayer should be added on screen for iOS 16.");
} else {
XCTAssertNil(player.playerLayer, @"AVPlayerLayer should not be present before iOS 16.");
}
XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present.");
XCTAssertNotNil(player.playerLayer.superlayer, @"AVPlayerLayer should be added on screen.");
}

- (void)testSeekToInvokesTextureFrameAvailableOnTextureRegistry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ - (void)onDisplayLink:(CADisplayLink *)link {
@interface FLTVideoPlayer : NSObject <FlutterTexture, FlutterStreamHandler>
@property(readonly, nonatomic) AVPlayer *player;
@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput;
/// An invisible player layer used to access the pixel buffers in protected video streams in iOS 16.
// This is to fix 2 bugs: 1. blank video for encrypted video streams on iOS 16
// (https://github.com/flutter/flutter/issues/111457) and 2. swapped width and height for some video
// streams (not just iOS 16). (https://github.com/flutter/flutter/issues/109116).
// An invisible AVPlayerLayer is used to overwrite the protection of pixel buffers in those streams
// for issue #1, and restore the correct width and height for issue #2.
@property(readonly, nonatomic) AVPlayerLayer *playerLayer;
@property(readonly, nonatomic) CADisplayLink *displayLink;
@property(nonatomic) FlutterEventChannel *eventChannel;
Expand Down Expand Up @@ -134,17 +138,13 @@ NS_INLINE CGFloat radiansToDegrees(CGFloat radians) {
return degrees;
};

NS_INLINE UIViewController *rootViewController() API_AVAILABLE(ios(16.0)) {
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
if ([scene isKindOfClass:UIWindowScene.class]) {
for (UIWindow *window in ((UIWindowScene *)scene).windows) {
if (window.isKeyWindow) {
return window.rootViewController;
}
}
}
}
return nil;
NS_INLINE UIViewController *rootViewController() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// TODO: (hellohuanlin) Provide a non-deprecated codepath. See
// https://github.com/flutter/flutter/issues/104117
return UIApplication.sharedApplication.keyWindow.rootViewController;
#pragma clang diagnostic pop
}

- (AVMutableVideoComposition *)getVideoCompositionWithTransform:(CGAffineTransform)transform
Expand Down Expand Up @@ -242,13 +242,13 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item
_player = [AVPlayer playerWithPlayerItem:item];
_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;

// This is to fix a bug (https://github.com/flutter/flutter/issues/111457) in iOS 16 with blank
// video for encrypted video streams. An invisible AVPlayerLayer is used to overwrite the
// protection of pixel buffers in those streams.
if (@available(iOS 16.0, *)) {
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
[rootViewController().view.layer addSublayer:_playerLayer];
}
// This is to fix 2 bugs: 1. blank video for encrypted video streams on iOS 16
// (https://github.com/flutter/flutter/issues/111457) and 2. swapped width and height for some
// video streams (not just iOS 16). (https://github.com/flutter/flutter/issues/109116). An
// invisible AVPlayerLayer is used to overwrite the protection of pixel buffers in those streams
// for issue #1, and restore the correct width and height for issue #2.
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
[rootViewController().view.layer addSublayer:_playerLayer];

[self createVideoOutputAndDisplayLink:frameUpdater];

Expand Down Expand Up @@ -481,9 +481,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments
/// so the channel is going to die or is already dead.
- (void)disposeSansEventChannel {
_disposed = YES;
if (@available(iOS 16.0, *)) {
[_playerLayer removeFromSuperlayer];
}
[_playerLayer removeFromSuperlayer];
[_displayLink invalidate];
AVPlayerItem *currentItem = self.player.currentItem;
[currentItem removeObserver:self forKeyPath:@"status"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: video_player_avfoundation
description: iOS implementation of the video_player plugin.
repository: https://github.com/flutter/plugins/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.3.6
version: 2.3.7

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

0 comments on commit 25e10b2

Please sign in to comment.