Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[video_player] Fixes a bug where the aspect ratio of some HLS videos are incorrectly inverted #6507

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I simply copied the code from another plugin. Fixing it is not the scope of this PR (tho I'm happy to help if needed).

}

- (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