From 16d3d7a0146b6d37dc9d65b73b4c6f235b716056 Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:55:45 +0200 Subject: [PATCH 1/8] send video load failure even when eventsink was initialized late --- .../video_player_avfoundation/CHANGELOG.md | 5 ++ .../darwin/RunnerTests/VideoPlayerTests.m | 33 ++++++++++ .../FVPVideoPlayerPlugin.m | 66 +++++++++++++++---- .../video_player_avfoundation/pubspec.yaml | 2 +- 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 4ea05f7f1a9e..53158f631bf5 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.6.2 + +* Fixes VideoPlayerController.initialize() future never resolving with invalid video file. +* Adds more details to the error message returned by VideoPlayerController.initialize(). + ## 2.6.1 * Adds files to make include directory permanent. diff --git a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m index 3ec96e78538a..02b9199a74fa 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -790,6 +790,39 @@ - (void)testPublishesInRegistration { XCTAssertTrue([publishedValue isKindOfClass:[FVPVideoPlayerPlugin class]]); } +- (void)testFailedToLoadVideoEventShouldBeAlwaysSent { + NSObject *registrar = + [GetPluginRegistry() registrarForPlugin:@"testFailedToLoadVideoEventShouldBeAlwaysSent"]; + FVPVideoPlayerPlugin *videoPlayerPlugin = + [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; + FlutterError *error; + + [videoPlayerPlugin initialize:&error]; + + FVPCreationOptions *create = [FVPCreationOptions makeWithAsset:nil + uri:@"" + packageName:nil + formatHint:nil + httpHeaders:@{}]; + NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + XCTAssertNotNil(player); + + [self keyValueObservingExpectationForObject:(id)player.player.currentItem + keyPath:@"status" + expectedValue:@(AVPlayerItemStatusFailed)]; + [self waitForExpectationsWithTimeout:10.0 handler:nil]; + + XCTestExpectation *failedExpectation = [self expectationWithDescription:@"failed"]; + [player onListenWithArguments:nil + eventSink:^(FlutterError *event) { + if ([event isKindOfClass:FlutterError.class]) { + [failedExpectation fulfill]; + } + }]; + [self waitForExpectationsWithTimeout:10.0 handler:nil]; +} + #if TARGET_OS_IOS - (void)validateTransformFixForOrientation:(UIImageOrientation)orientation { AVAssetTrack *track = [[FakeAVAssetTrack alloc] initWithOrientation:orientation]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 14ee7ccefde2..571c19bde6d4 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -345,13 +345,7 @@ - (void)observeValueForKeyPath:(NSString *)path AVPlayerItem *item = (AVPlayerItem *)object; switch (item.status) { case AVPlayerItemStatusFailed: - if (_eventSink != nil) { - _eventSink([FlutterError - errorWithCode:@"VideoError" - message:[@"Failed to load video: " - stringByAppendingString:[item.error localizedDescription]] - details:nil]); - } + [self sendFailedToLoadVideoEvent:item.error]; break; case AVPlayerItemStatusUnknown: break; @@ -406,9 +400,46 @@ - (void)updatePlayingState { _displayLink.running = _isPlaying || self.waitingForFrame; } +- (void)sendFailedToLoadVideoEvent:(NSError *)error { + if (!NSThread.isMainThread) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self sendFailedToLoadVideoEvent:error]; + }); + return; + } + if (_eventSink == nil) { + return; + } + __block NSString *message = @"Failed to load video"; + void (^add)(NSString *) = ^(NSString *detail) { + if (detail != nil) { + message = [message stringByAppendingFormat:@": %@", detail]; + } + }; + NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; + // add more details to error message + // https://github.com/flutter/flutter/issues/56665 + add(error.localizedDescription); + add(error.localizedFailureReason); + add(underlyingError.localizedDescription); + add(underlyingError.localizedFailureReason); + _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); +} + - (void)setupEventSinkIfReadyToPlay { if (_eventSink && !_isInitialized) { AVPlayerItem *currentItem = self.player.currentItem; + // if status is Failed here then this was called from onListenWithArguments which means + // _eventSink was nil when was called observeValueForKeyPath with updated Failed status + // and error was not sent and never will be so it is needed to send it here to have + // future returned by initialize resolved instead of in state of infinite waiting, + // see comment in onListenWithArguments + // https://github.com/flutter/flutter/issues/151475 + // https://github.com/flutter/flutter/issues/147707 + if (currentItem.status == AVPlayerItemStatusFailed) { + [self sendFailedToLoadVideoEvent:currentItem.error]; + return; + } CGSize size = currentItem.presentationSize; CGFloat width = size.width; CGFloat height = size.height; @@ -417,13 +448,24 @@ - (void)setupEventSinkIfReadyToPlay { AVAsset *asset = currentItem.asset; if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { void (^trackCompletionHandler)(void) = ^{ - if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { + NSError *error; + switch ([asset statusOfValueForKey:@"tracks" error:&error]) { + case AVKeyValueStatusLoaded: + // This completion block will run on an AVFoundation background queue. + // Hop back to the main thread to set up event sink. + [self performSelector:_cmd + onThread:NSThread.mainThread + withObject:self + waitUntilDone:NO]; + break; // Cancelled, or something failed. - return; + case AVKeyValueStatusFailed: + // if something failed then future should result in error + [self sendFailedToLoadVideoEvent:error]; + break; + default: + break; } - // This completion block will run on an AVFoundation background queue. - // Hop back to the main thread to set up event sink. - [self performSelector:_cmd onThread:NSThread.mainThread withObject:self waitUntilDone:NO]; }; [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:trackCompletionHandler]; diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 674684ee789d..5fbf5aa50ef1 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 and macOS implementation of the video_player plugin. repository: https://github.com/flutter/packages/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.6.1 +version: 2.6.2 environment: sdk: ^3.2.3 From 12a061e239361a0d849011cdd78a3adb51ef640a Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:25:00 +0200 Subject: [PATCH 2/8] move dispatch_async and change comments --- .../FVPVideoPlayerPlugin.m | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 571c19bde6d4..ac34c5308273 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -401,12 +401,6 @@ - (void)updatePlayingState { } - (void)sendFailedToLoadVideoEvent:(NSError *)error { - if (!NSThread.isMainThread) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self sendFailedToLoadVideoEvent:error]; - }); - return; - } if (_eventSink == nil) { return; } @@ -417,7 +411,6 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { } }; NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; - // add more details to error message // https://github.com/flutter/flutter/issues/56665 add(error.localizedDescription); add(error.localizedFailureReason); @@ -429,10 +422,9 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { - (void)setupEventSinkIfReadyToPlay { if (_eventSink && !_isInitialized) { AVPlayerItem *currentItem = self.player.currentItem; - // if status is Failed here then this was called from onListenWithArguments which means - // _eventSink was nil when was called observeValueForKeyPath with updated Failed status - // and error was not sent and never will be so it is needed to send it here to have - // future returned by initialize resolved instead of in state of infinite waiting, + // if status is Failed this was probably called from onListenWithArguments, which means + // _eventSink was initialized to non-nil probably only after observeValueForKeyPath already + // observed Failed status and it did not send error, therefore we need to send it here // see comment in onListenWithArguments // https://github.com/flutter/flutter/issues/151475 // https://github.com/flutter/flutter/issues/147707 @@ -461,7 +453,9 @@ - (void)setupEventSinkIfReadyToPlay { // Cancelled, or something failed. case AVKeyValueStatusFailed: // if something failed then future should result in error - [self sendFailedToLoadVideoEvent:error]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self sendFailedToLoadVideoEvent:error]; + }); break; default: break; From 4ab3c53b83a3efd9eadf8c5f648eb1817c592734 Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:36:05 +0200 Subject: [PATCH 3/8] add braces --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index ac34c5308273..46b4dcf6bbb8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -451,12 +451,13 @@ - (void)setupEventSinkIfReadyToPlay { waitUntilDone:NO]; break; // Cancelled, or something failed. - case AVKeyValueStatusFailed: + case AVKeyValueStatusFailed: { // if something failed then future should result in error dispatch_async(dispatch_get_main_queue(), ^{ [self sendFailedToLoadVideoEvent:error]; }); break; + } default: break; } From 1e0964f64c0a847ade8642fdf6fe760c51d4d087 Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:09:19 +0200 Subject: [PATCH 4/8] rename function --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 46b4dcf6bbb8..fbb3b5f47408 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -351,7 +351,7 @@ - (void)observeValueForKeyPath:(NSString *)path break; case AVPlayerItemStatusReadyToPlay: [item addOutput:_videoOutput]; - [self setupEventSinkIfReadyToPlay]; + [self setupEventSinkIfReadyToPlayOrReportFailure]; [self updatePlayingState]; break; } @@ -361,7 +361,7 @@ - (void)observeValueForKeyPath:(NSString *)path // Due to an apparent bug, when the player item is ready, it still may not have determined // its presentation size or duration. When these properties are finally set, re-check if // all required properties and instantiate the event sink if it is not already set up. - [self setupEventSinkIfReadyToPlay]; + [self setupEventSinkIfReadyToPlayOrReportFailure]; [self updatePlayingState]; } } else if (context == playbackLikelyToKeepUpContext) { @@ -411,7 +411,6 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { } }; NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; - // https://github.com/flutter/flutter/issues/56665 add(error.localizedDescription); add(error.localizedFailureReason); add(underlyingError.localizedDescription); @@ -419,7 +418,7 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); } -- (void)setupEventSinkIfReadyToPlay { +- (void)setupEventSinkIfReadyToPlayOrReportFailure { if (_eventSink && !_isInitialized) { AVPlayerItem *currentItem = self.player.currentItem; // if status is Failed this was probably called from onListenWithArguments, which means @@ -624,7 +623,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments // This line ensures the 'initialized' event is sent when the event // 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function // onListenWithArguments is called) - [self setupEventSinkIfReadyToPlay]; + [self setupEventSinkIfReadyToPlayOrReportFailure]; return nil; } From 89db4867cef748d2a208e61104dc62b788c397ce Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:24:23 +0200 Subject: [PATCH 5/8] move failure check outside --- .../FVPVideoPlayerPlugin.m | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index fbb3b5f47408..c7fab9ca2c74 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -351,7 +351,7 @@ - (void)observeValueForKeyPath:(NSString *)path break; case AVPlayerItemStatusReadyToPlay: [item addOutput:_videoOutput]; - [self setupEventSinkIfReadyToPlayOrReportFailure]; + [self setupEventSinkIfReadyToPlay]; [self updatePlayingState]; break; } @@ -361,7 +361,7 @@ - (void)observeValueForKeyPath:(NSString *)path // Due to an apparent bug, when the player item is ready, it still may not have determined // its presentation size or duration. When these properties are finally set, re-check if // all required properties and instantiate the event sink if it is not already set up. - [self setupEventSinkIfReadyToPlayOrReportFailure]; + [self setupEventSinkIfReadyToPlay]; [self updatePlayingState]; } } else if (context == playbackLikelyToKeepUpContext) { @@ -418,19 +418,9 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); } -- (void)setupEventSinkIfReadyToPlayOrReportFailure { +- (void)setupEventSinkIfReadyToPlay { if (_eventSink && !_isInitialized) { AVPlayerItem *currentItem = self.player.currentItem; - // if status is Failed this was probably called from onListenWithArguments, which means - // _eventSink was initialized to non-nil probably only after observeValueForKeyPath already - // observed Failed status and it did not send error, therefore we need to send it here - // see comment in onListenWithArguments - // https://github.com/flutter/flutter/issues/151475 - // https://github.com/flutter/flutter/issues/147707 - if (currentItem.status == AVPlayerItemStatusFailed) { - [self sendFailedToLoadVideoEvent:currentItem.error]; - return; - } CGSize size = currentItem.presentationSize; CGFloat width = size.width; CGFloat height = size.height; @@ -623,7 +613,14 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments // This line ensures the 'initialized' event is sent when the event // 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function // onListenWithArguments is called) - [self setupEventSinkIfReadyToPlayOrReportFailure]; + // and also send error in similar case with 'AVPlayerItemStatusFailed' + // https://github.com/flutter/flutter/issues/151475 + // https://github.com/flutter/flutter/issues/147707 + if (self.player.currentItem.status == AVPlayerItemStatusFailed) { + [self sendFailedToLoadVideoEvent:self.player.currentItem.error]; + return nil; + } + [self setupEventSinkIfReadyToPlay]; return nil; } From 1a6fd6f73242c61f173eebcd6838b5bb48014a6c Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:30:55 +0200 Subject: [PATCH 6/8] prefer to use error from tracks loading --- .../FVPVideoPlayerPlugin.m | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index c7fab9ca2c74..75eef105e411 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -345,7 +345,7 @@ - (void)observeValueForKeyPath:(NSString *)path AVPlayerItem *item = (AVPlayerItem *)object; switch (item.status) { case AVPlayerItemStatusFailed: - [self sendFailedToLoadVideoEvent:item.error]; + [self sendFailedToLoadVideoEvent]; break; case AVPlayerItemStatusUnknown: break; @@ -400,14 +400,19 @@ - (void)updatePlayingState { _displayLink.running = _isPlaying || self.waitingForFrame; } -- (void)sendFailedToLoadVideoEvent:(NSError *)error { +- (void)sendFailedToLoadVideoEvent { if (_eventSink == nil) { return; } - __block NSString *message = @"Failed to load video"; + // Prefer more detailed error information from tracks loading. + NSError *error; + if ([self.player.currentItem.asset statusOfValueForKey:@"tracks" error:&error] != AVKeyValueStatusFailed) { + error = self.player.currentItem.error; + } + __block NSMutableOrderedSet *details = [NSMutableOrderedSet orderedSetWithObject:@"Failed to load video"]; void (^add)(NSString *) = ^(NSString *detail) { if (detail != nil) { - message = [message stringByAppendingFormat:@": %@", detail]; + [details addObject:detail]; } }; NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; @@ -415,6 +420,7 @@ - (void)sendFailedToLoadVideoEvent:(NSError *)error { add(error.localizedFailureReason); add(underlyingError.localizedDescription); add(underlyingError.localizedFailureReason); + NSString *message = [details.array componentsJoinedByString:@": "]; _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); } @@ -429,27 +435,13 @@ - (void)setupEventSinkIfReadyToPlay { AVAsset *asset = currentItem.asset; if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { void (^trackCompletionHandler)(void) = ^{ - NSError *error; - switch ([asset statusOfValueForKey:@"tracks" error:&error]) { - case AVKeyValueStatusLoaded: - // This completion block will run on an AVFoundation background queue. - // Hop back to the main thread to set up event sink. - [self performSelector:_cmd - onThread:NSThread.mainThread - withObject:self - waitUntilDone:NO]; - break; + if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { // Cancelled, or something failed. - case AVKeyValueStatusFailed: { - // if something failed then future should result in error - dispatch_async(dispatch_get_main_queue(), ^{ - [self sendFailedToLoadVideoEvent:error]; - }); - break; - } - default: - break; + return; } + // This completion block will run on an AVFoundation background queue. + // Hop back to the main thread to set up event sink. + [self performSelector:_cmd onThread:NSThread.mainThread withObject:self waitUntilDone:NO]; }; [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:trackCompletionHandler]; @@ -617,7 +609,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments // https://github.com/flutter/flutter/issues/151475 // https://github.com/flutter/flutter/issues/147707 if (self.player.currentItem.status == AVPlayerItemStatusFailed) { - [self sendFailedToLoadVideoEvent:self.player.currentItem.error]; + [self sendFailedToLoadVideoEvent]; return nil; } [self setupEventSinkIfReadyToPlay]; From 60330dc4dec16aed60bdc9a8a3dbdf59534d8d2a Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:46:26 +0200 Subject: [PATCH 7/8] fix format --- .../video_player/video_player_avfoundation/CHANGELOG.md | 2 +- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 6 ++++-- .../video_player/video_player_avfoundation/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 02c244af1bdb..a7d6a91b8730 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.6.2 +## 2.6.3 * Fixes VideoPlayerController.initialize() future never resolving with invalid video file. * Adds more details to the error message returned by VideoPlayerController.initialize(). diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 75eef105e411..05e0e578a6b5 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -406,10 +406,12 @@ - (void)sendFailedToLoadVideoEvent { } // Prefer more detailed error information from tracks loading. NSError *error; - if ([self.player.currentItem.asset statusOfValueForKey:@"tracks" error:&error] != AVKeyValueStatusFailed) { + if ([self.player.currentItem.asset statusOfValueForKey:@"tracks" + error:&error] != AVKeyValueStatusFailed) { error = self.player.currentItem.error; } - __block NSMutableOrderedSet *details = [NSMutableOrderedSet orderedSetWithObject:@"Failed to load video"]; + __block NSMutableOrderedSet *details = + [NSMutableOrderedSet orderedSetWithObject:@"Failed to load video"]; void (^add)(NSString *) = ^(NSString *detail) { if (detail != nil) { [details addObject:detail]; diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 63952af7c43e..0d04e93ed114 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 and macOS implementation of the video_player plugin. repository: https://github.com/flutter/packages/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.6.2 +version: 2.6.3 environment: sdk: ^3.3.0 From ab57c3373eafc947052f97b14e0813eac791c59c Mon Sep 17 00:00:00 2001 From: misos1 <30872003+misos1@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:58:14 +0200 Subject: [PATCH 8/8] fix format --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 05e0e578a6b5..88f7d3722f86 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -410,7 +410,7 @@ - (void)sendFailedToLoadVideoEvent { error:&error] != AVKeyValueStatusFailed) { error = self.player.currentItem.error; } - __block NSMutableOrderedSet *details = + __block NSMutableOrderedSet *details = [NSMutableOrderedSet orderedSetWithObject:@"Failed to load video"]; void (^add)(NSString *) = ^(NSString *detail) { if (detail != nil) {