From 82d533370b3496b788bf7aaa44286d63d77f6d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 16:23:12 +0100 Subject: [PATCH 001/167] Extract FVPFrameUpdater and FVPVideoPlayer from plugin file to separate files --- .../FVPFrameUpdater.m | 24 + .../FVPVideoPlayer.m | 576 ++++++++++++++++ .../FVPVideoPlayerPlugin.m | 635 +----------------- .../FVPFrameUpdater.h | 24 + .../FVPVideoPlayer.h | 87 +++ 5 files changed, 713 insertions(+), 633 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m new file mode 100644 index 00000000000..42f5e1dc743 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m @@ -0,0 +1,24 @@ +// 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 "./include/video_player_avfoundation/FVPFrameUpdater.h" + +@implementation FVPFrameUpdater +- (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry { + NSAssert(self, @"super init cannot be nil"); + if (self == nil) return nil; + _registry = registry; + _lastKnownAvailableTime = kCMTimeInvalid; + return self; +} + +- (void)displayLinkFired { + // Only report a new frame if one is actually available. + CMTime outputItemTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; + if ([self.videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { + _lastKnownAvailableTime = outputItemTime; + [_registry textureFrameAvailable:_textureId]; + } +} +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m new file mode 100644 index 00000000000..c9df951f4c0 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -0,0 +1,576 @@ +// 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 "./include/video_player_avfoundation/FVPVideoPlayer.h" +#import "./include/video_player_avfoundation/AVAssetTrackUtils.h" + +#pragma mark - + +static void *timeRangeContext = &timeRangeContext; +static void *statusContext = &statusContext; +static void *presentationSizeContext = &presentationSizeContext; +static void *durationContext = &durationContext; +static void *playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext; +static void *rateContext = &rateContext; + +@implementation FVPVideoPlayer +- (instancetype)initWithAsset:(NSString *)asset + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; +#if TARGET_OS_OSX + // See https://github.com/flutter/flutter/issues/135302 + // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. + if (!path) { + path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; + } +#endif + return [self initWithURL:[NSURL fileURLWithPath:path] + frameUpdater:frameUpdater + displayLink:displayLink + httpHeaders:@{} + avFactory:avFactory + registrar:registrar]; +} + +- (void)dealloc { + if (!_disposed) { + [self removeKeyValueObservers]; + } +} + +- (void)addObserversForItem:(AVPlayerItem *)item player:(AVPlayer *)player { + [item addObserver:self + forKeyPath:@"loadedTimeRanges" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:timeRangeContext]; + [item addObserver:self + forKeyPath:@"status" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:statusContext]; + [item addObserver:self + forKeyPath:@"presentationSize" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:presentationSizeContext]; + [item addObserver:self + forKeyPath:@"duration" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:durationContext]; + [item addObserver:self + forKeyPath:@"playbackLikelyToKeepUp" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:playbackLikelyToKeepUpContext]; + + // Add observer to AVPlayer instead of AVPlayerItem since the AVPlayerItem does not have a "rate" + // property + [player addObserver:self + forKeyPath:@"rate" + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:rateContext]; + + // Add an observer that will respond to itemDidPlayToEndTime + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(itemDidPlayToEndTime:) + name:AVPlayerItemDidPlayToEndTimeNotification + object:item]; +} + +- (void)itemDidPlayToEndTime:(NSNotification *)notification { + if (_isLooping) { + AVPlayerItem *p = [notification object]; + [p seekToTime:kCMTimeZero completionHandler:nil]; + } else { + if (_eventSink) { + _eventSink(@{@"event" : @"completed"}); + } + } +} + +const int64_t TIME_UNSET = -9223372036854775807; + +NS_INLINE int64_t FVPCMTimeToMillis(CMTime time) { + // When CMTIME_IS_INDEFINITE return a value that matches TIME_UNSET from ExoPlayer2 on Android. + // Fixes https://github.com/flutter/flutter/issues/48670 + if (CMTIME_IS_INDEFINITE(time)) return TIME_UNSET; + if (time.timescale == 0) return 0; + return time.value * 1000 / time.timescale; +} + +NS_INLINE CGFloat radiansToDegrees(CGFloat radians) { + // Input range [-pi, pi] or [-180, 180] + CGFloat degrees = GLKMathRadiansToDegrees((float)radians); + if (degrees < 0) { + // Convert -90 to 270 and -180 to 180 + return degrees + 360; + } + // Output degrees in between [0, 360] + return degrees; +}; + +- (AVMutableVideoComposition *)getVideoCompositionWithTransform:(CGAffineTransform)transform + withAsset:(AVAsset *)asset + withVideoTrack:(AVAssetTrack *)videoTrack { + AVMutableVideoCompositionInstruction *instruction = + [AVMutableVideoCompositionInstruction videoCompositionInstruction]; + instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [asset duration]); + AVMutableVideoCompositionLayerInstruction *layerInstruction = + [AVMutableVideoCompositionLayerInstruction + videoCompositionLayerInstructionWithAssetTrack:videoTrack]; + [layerInstruction setTransform:_preferredTransform atTime:kCMTimeZero]; + + AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; + instruction.layerInstructions = @[ layerInstruction ]; + videoComposition.instructions = @[ instruction ]; + + // If in portrait mode, switch the width and height of the video + CGFloat width = videoTrack.naturalSize.width; + CGFloat height = videoTrack.naturalSize.height; + NSInteger rotationDegrees = + (NSInteger)round(radiansToDegrees(atan2(_preferredTransform.b, _preferredTransform.a))); + if (rotationDegrees == 90 || rotationDegrees == 270) { + width = videoTrack.naturalSize.height; + height = videoTrack.naturalSize.width; + } + videoComposition.renderSize = CGSizeMake(width, height); + + // TODO(@recastrodiaz): should we use videoTrack.nominalFrameRate ? + // Currently set at a constant 30 FPS + videoComposition.frameDuration = CMTimeMake(1, 30); + + return videoComposition; +} + +- (instancetype)initWithURL:(NSURL *)url + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:(nonnull NSDictionary *)headers + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + NSDictionary *options = nil; + if ([headers count] != 0) { + options = @{@"AVURLAssetHTTPHeaderFieldsKey" : headers}; + } + AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:options]; + AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:urlAsset]; + return [self initWithPlayerItem:item + frameUpdater:frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:avFactory + registrar:registrar]; +} + +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + + _registrar = registrar; + _frameUpdater = frameUpdater; + + AVAsset *asset = [item asset]; + void (^assetCompletionHandler)(void) = ^{ + if ([asset statusOfValueForKey:@"tracks" error:nil] == AVKeyValueStatusLoaded) { + NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; + if ([tracks count] > 0) { + AVAssetTrack *videoTrack = tracks[0]; + void (^trackCompletionHandler)(void) = ^{ + if (self->_disposed) return; + if ([videoTrack statusOfValueForKey:@"preferredTransform" + error:nil] == AVKeyValueStatusLoaded) { + // Rotate the video by using a videoComposition and the preferredTransform + self->_preferredTransform = FVPGetStandardizedTransformForTrack(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 + // use with media served using HTTP Live Streaming. + AVMutableVideoComposition *videoComposition = + [self getVideoCompositionWithTransform:self->_preferredTransform + withAsset:asset + withVideoTrack:videoTrack]; + item.videoComposition = videoComposition; + } + }; + [videoTrack loadValuesAsynchronouslyForKeys:@[ @"preferredTransform" ] + completionHandler:trackCompletionHandler]; + } + } + }; + + _player = [avFactory playerWithPlayerItem:item]; + _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; + + // 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]; + [self.flutterViewLayer addSublayer:_playerLayer]; + + // Configure output. + _displayLink = displayLink; + NSDictionary *pixBuffAttributes = @{ + (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA), + (id)kCVPixelBufferIOSurfacePropertiesKey : @{} + }; + _videoOutput = [avFactory videoOutputWithPixelBufferAttributes:pixBuffAttributes]; + frameUpdater.videoOutput = _videoOutput; + + [self addObserversForItem:item player:_player]; + + [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:assetCompletionHandler]; + + return self; +} + +- (void)observeValueForKeyPath:(NSString *)path + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (context == timeRangeContext) { + if (_eventSink != nil) { + NSMutableArray *> *values = [[NSMutableArray alloc] init]; + for (NSValue *rangeValue in [object loadedTimeRanges]) { + CMTimeRange range = [rangeValue CMTimeRangeValue]; + int64_t start = FVPCMTimeToMillis(range.start); + [values addObject:@[ @(start), @(start + FVPCMTimeToMillis(range.duration)) ]]; + } + _eventSink(@{@"event" : @"bufferingUpdate", @"values" : values}); + } + } else if (context == statusContext) { + AVPlayerItem *item = (AVPlayerItem *)object; + switch (item.status) { + case AVPlayerItemStatusFailed: + [self sendFailedToLoadVideoEvent]; + break; + case AVPlayerItemStatusUnknown: + break; + case AVPlayerItemStatusReadyToPlay: + [item addOutput:_videoOutput]; + [self setupEventSinkIfReadyToPlay]; + [self updatePlayingState]; + break; + } + } else if (context == presentationSizeContext || context == durationContext) { + AVPlayerItem *item = (AVPlayerItem *)object; + if (item.status == AVPlayerItemStatusReadyToPlay) { + // 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 updatePlayingState]; + } + } else if (context == playbackLikelyToKeepUpContext) { + [self updatePlayingState]; + if ([[_player currentItem] isPlaybackLikelyToKeepUp]) { + if (_eventSink != nil) { + _eventSink(@{@"event" : @"bufferingEnd"}); + } + } else { + if (_eventSink != nil) { + _eventSink(@{@"event" : @"bufferingStart"}); + } + } + } else if (context == rateContext) { + // Important: Make sure to cast the object to AVPlayer when observing the rate property, + // as it is not available in AVPlayerItem. + AVPlayer *player = (AVPlayer *)object; + if (_eventSink != nil) { + _eventSink( + @{@"event" : @"isPlayingStateUpdate", @"isPlaying" : player.rate > 0 ? @YES : @NO}); + } + } +} + +- (void)updatePlayingState { + if (!_isInitialized) { + return; + } + if (_isPlaying) { + [_player play]; + } else { + [_player pause]; + } + // If the texture is still waiting for an expected frame, the display link needs to keep + // running until it arrives regardless of the play/pause state. + _displayLink.running = _isPlaying || self.waitingForFrame; +} + +- (void)sendFailedToLoadVideoEvent { + if (_eventSink == nil) { + return; + } + // 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) { + [details addObject:detail]; + } + }; + NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; + add(error.localizedDescription); + add(error.localizedFailureReason); + add(underlyingError.localizedDescription); + add(underlyingError.localizedFailureReason); + NSString *message = [details.array componentsJoinedByString:@": "]; + _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); +} + +- (void)setupEventSinkIfReadyToPlay { + if (_eventSink && !_isInitialized) { + AVPlayerItem *currentItem = self.player.currentItem; + CGSize size = currentItem.presentationSize; + CGFloat width = size.width; + CGFloat height = size.height; + + // Wait until tracks are loaded to check duration or if there are any videos. + AVAsset *asset = currentItem.asset; + if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { + void (^trackCompletionHandler)(void) = ^{ + if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { + // Cancelled, or something failed. + 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]; + return; + } + + BOOL hasVideoTracks = [asset tracksWithMediaType:AVMediaTypeVideo].count != 0; + BOOL hasNoTracks = asset.tracks.count == 0; + + // The player has not yet initialized when it has no size, unless it is an audio-only track. + // HLS m3u8 video files never load any tracks, and are also not yet initialized until they have + // a size. + if ((hasVideoTracks || hasNoTracks) && height == CGSizeZero.height && + width == CGSizeZero.width) { + return; + } + // The player may be initialized but still needs to determine the duration. + int64_t duration = [self duration]; + if (duration == 0) { + return; + } + + _isInitialized = YES; + _eventSink(@{ + @"event" : @"initialized", + @"duration" : @(duration), + @"width" : @(width), + @"height" : @(height) + }); + } +} + +- (void)play { + _isPlaying = YES; + [self updatePlayingState]; +} + +- (void)pause { + _isPlaying = NO; + [self updatePlayingState]; +} + +- (int64_t)position { + return FVPCMTimeToMillis([_player currentTime]); +} + +- (int64_t)duration { + // Note: https://openradar.appspot.com/radar?id=4968600712511488 + // `[AVPlayerItem duration]` can be `kCMTimeIndefinite`, + // use `[[AVPlayerItem asset] duration]` instead. + return FVPCMTimeToMillis([[[_player currentItem] asset] duration]); +} + +- (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { + CMTime previousCMTime = _player.currentTime; + CMTime targetCMTime = CMTimeMake(location, 1000); + CMTimeValue duration = _player.currentItem.asset.duration.value; + // Without adding tolerance when seeking to duration, + // seekToTime will never complete, and this call will hang. + // see issue https://github.com/flutter/flutter/issues/124475. + CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero; + [_player seekToTime:targetCMTime + toleranceBefore:tolerance + toleranceAfter:tolerance + completionHandler:^(BOOL completed) { + if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { + // Ensure that a frame is drawn once available, even if currently paused. In theory a race + // is possible here where the new frame has already drawn by the time this code runs, and + // the display link stays on indefinitely, but that should be relatively harmless. This + // must use the display link rather than just informing the engine that a new frame is + // available because the seek completing doesn't guarantee that the pixel buffer is + // already available. + [self expectFrame]; + } + + if (completionHandler) { + completionHandler(completed); + } + }]; +} + +- (void)expectFrame { + self.waitingForFrame = YES; + self.displayLink.running = YES; +} + +- (void)setIsLooping:(BOOL)isLooping { + _isLooping = isLooping; +} + +- (void)setVolume:(double)volume { + _player.volume = (float)((volume < 0.0) ? 0.0 : ((volume > 1.0) ? 1.0 : volume)); +} + +- (void)setPlaybackSpeed:(double)speed { + // See https://developer.apple.com/library/archive/qa/qa1772/_index.html for an explanation of + // these checks. + if (speed > 2.0 && !_player.currentItem.canPlayFastForward) { + if (_eventSink != nil) { + _eventSink([FlutterError errorWithCode:@"VideoError" + message:@"Video cannot be fast-forwarded beyond 2.0x" + details:nil]); + } + return; + } + + if (speed < 1.0 && !_player.currentItem.canPlaySlowForward) { + if (_eventSink != nil) { + _eventSink([FlutterError errorWithCode:@"VideoError" + message:@"Video cannot be slow-forwarded" + details:nil]); + } + return; + } + + _player.rate = speed; +} + +- (CVPixelBufferRef)copyPixelBuffer { + CVPixelBufferRef buffer = NULL; + CMTime outputItemTime = [_videoOutput itemTimeForHostTime:CACurrentMediaTime()]; + if ([_videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { + buffer = [_videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; + } else { + // If the current time isn't available yet, use the time that was checked when informing the + // engine that a frame was available (if any). + CMTime lastAvailableTime = self.frameUpdater.lastKnownAvailableTime; + if (CMTIME_IS_VALID(lastAvailableTime)) { + buffer = [_videoOutput copyPixelBufferForItemTime:lastAvailableTime itemTimeForDisplay:NULL]; + } + } + + if (self.waitingForFrame && buffer) { + self.waitingForFrame = NO; + // If the display link was only running temporarily to pick up a new frame while the video was + // paused, stop it again. + if (!self.isPlaying) { + self.displayLink.running = NO; + } + } + + return buffer; +} + +- (void)onTextureUnregistered:(NSObject *)texture { + dispatch_async(dispatch_get_main_queue(), ^{ + [self dispose]; + }); +} + +- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { + _eventSink = nil; + return nil; +} + +- (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments + eventSink:(nonnull FlutterEventSink)events { + _eventSink = events; + // TODO(@recastrodiaz): remove the line below when the race condition is resolved: + // https://github.com/flutter/flutter/issues/21483 + // This line ensures the 'initialized' event is sent when the event + // 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function + // onListenWithArguments is called) + // 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]; + return nil; + } + [self setupEventSinkIfReadyToPlay]; + return nil; +} + +/// This method allows you to dispose without touching the event channel. This +/// is useful for the case where the Engine is in the process of deconstruction +/// so the channel is going to die or is already dead. +- (void)disposeSansEventChannel { + // This check prevents the crash caused by removing the KVO observers twice. + // When performing a Hot Restart, the leftover players are disposed once directly + // by [FVPVideoPlayerPlugin initialize:] method and then disposed again by + // [FVPVideoPlayer onTextureUnregistered:] call leading to possible over-release. + if (_disposed) { + return; + } + + _disposed = YES; + [_playerLayer removeFromSuperlayer]; + _displayLink = nil; + [self removeKeyValueObservers]; + + [self.player replaceCurrentItemWithPlayerItem:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)dispose { + [self disposeSansEventChannel]; + [_eventChannel setStreamHandler:nil]; +} + +- (CALayer *)flutterViewLayer { +#if TARGET_OS_OSX + return self.registrar.view.layer; +#else +#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 + UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; +#pragma clang diagnostic pop + return root.view.layer; +#endif +} + +/// Removes all key-value observers set up for the player. +/// +/// This is called from dealloc, so must not use any methods on self. +- (void)removeKeyValueObservers { + AVPlayerItem *currentItem = _player.currentItem; + [currentItem removeObserver:self forKeyPath:@"status"]; + [currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"]; + [currentItem removeObserver:self forKeyPath:@"presentationSize"]; + [currentItem removeObserver:self forKeyPath:@"duration"]; + [currentItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; + [_player removeObserver:self forKeyPath:@"rate"]; +} + +@end 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 88f7d3722f8..fbca6e02a4e 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 @@ -6,44 +6,17 @@ #import "FVPVideoPlayerPlugin_Test.h" #import -#import #import "./include/video_player_avfoundation/AVAssetTrackUtils.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" +#import "./include/video_player_avfoundation/FVPFrameUpdater.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/messages.g.h" #if !__has_feature(objc_arc) #error Code Requires ARC. #endif -@interface FVPFrameUpdater : NSObject -@property(nonatomic) int64_t textureId; -@property(nonatomic, weak, readonly) NSObject *registry; -// The output that this updater is managing. -@property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; -// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. -@property(nonatomic, assign) CMTime lastKnownAvailableTime; -@end - -@implementation FVPFrameUpdater -- (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry { - NSAssert(self, @"super init cannot be nil"); - if (self == nil) return nil; - _registry = registry; - _lastKnownAvailableTime = kCMTimeInvalid; - return self; -} - -- (void)displayLinkFired { - // Only report a new frame if one is actually available. - CMTime outputItemTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; - if ([self.videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { - _lastKnownAvailableTime = outputItemTime; - [_registry textureFrameAvailable:_textureId]; - } -} -@end - @interface FVPDefaultAVFactory : NSObject @end @@ -69,610 +42,6 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr @end -#pragma mark - - -@interface FVPVideoPlayer () -@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; -// The plugin registrar, to obtain view information from. -@property(nonatomic, weak) NSObject *registrar; -// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly) CALayer *flutterViewLayer; -@property(nonatomic) FlutterEventChannel *eventChannel; -@property(nonatomic) FlutterEventSink eventSink; -@property(nonatomic) CGAffineTransform preferredTransform; -@property(nonatomic, readonly) BOOL disposed; -@property(nonatomic, readonly) BOOL isPlaying; -@property(nonatomic) BOOL isLooping; -@property(nonatomic, readonly) BOOL isInitialized; -// The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic) FVPFrameUpdater *frameUpdater; -// The display link that drives frameUpdater. -@property(nonatomic) FVPDisplayLink *displayLink; -// Whether a new frame needs to be provided to the engine regardless of the current play/pause state -// (e.g., after a seek while paused). If YES, the display link should continue to run until the next -// frame is successfully provided. -@property(nonatomic, assign) BOOL waitingForFrame; - -- (instancetype)initWithURL:(NSURL *)url - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink - httpHeaders:(nonnull NSDictionary *)headers - avFactory:(id)avFactory - registrar:(NSObject *)registrar; - -// Tells the player to run its frame updater until it receives a frame, regardless of the -// play/pause state. -- (void)expectFrame; -@end - -static void *timeRangeContext = &timeRangeContext; -static void *statusContext = &statusContext; -static void *presentationSizeContext = &presentationSizeContext; -static void *durationContext = &durationContext; -static void *playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext; -static void *rateContext = &rateContext; - -@implementation FVPVideoPlayer -- (instancetype)initWithAsset:(NSString *)asset - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink - avFactory:(id)avFactory - registrar:(NSObject *)registrar { - NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; -#if TARGET_OS_OSX - // See https://github.com/flutter/flutter/issues/135302 - // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. - if (!path) { - path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; - } -#endif - return [self initWithURL:[NSURL fileURLWithPath:path] - frameUpdater:frameUpdater - displayLink:displayLink - httpHeaders:@{} - avFactory:avFactory - registrar:registrar]; -} - -- (void)dealloc { - if (!_disposed) { - [self removeKeyValueObservers]; - } -} - -- (void)addObserversForItem:(AVPlayerItem *)item player:(AVPlayer *)player { - [item addObserver:self - forKeyPath:@"loadedTimeRanges" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:timeRangeContext]; - [item addObserver:self - forKeyPath:@"status" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:statusContext]; - [item addObserver:self - forKeyPath:@"presentationSize" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:presentationSizeContext]; - [item addObserver:self - forKeyPath:@"duration" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:durationContext]; - [item addObserver:self - forKeyPath:@"playbackLikelyToKeepUp" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:playbackLikelyToKeepUpContext]; - - // Add observer to AVPlayer instead of AVPlayerItem since the AVPlayerItem does not have a "rate" - // property - [player addObserver:self - forKeyPath:@"rate" - options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew - context:rateContext]; - - // Add an observer that will respond to itemDidPlayToEndTime - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(itemDidPlayToEndTime:) - name:AVPlayerItemDidPlayToEndTimeNotification - object:item]; -} - -- (void)itemDidPlayToEndTime:(NSNotification *)notification { - if (_isLooping) { - AVPlayerItem *p = [notification object]; - [p seekToTime:kCMTimeZero completionHandler:nil]; - } else { - if (_eventSink) { - _eventSink(@{@"event" : @"completed"}); - } - } -} - -const int64_t TIME_UNSET = -9223372036854775807; - -NS_INLINE int64_t FVPCMTimeToMillis(CMTime time) { - // When CMTIME_IS_INDEFINITE return a value that matches TIME_UNSET from ExoPlayer2 on Android. - // Fixes https://github.com/flutter/flutter/issues/48670 - if (CMTIME_IS_INDEFINITE(time)) return TIME_UNSET; - if (time.timescale == 0) return 0; - return time.value * 1000 / time.timescale; -} - -NS_INLINE CGFloat radiansToDegrees(CGFloat radians) { - // Input range [-pi, pi] or [-180, 180] - CGFloat degrees = GLKMathRadiansToDegrees((float)radians); - if (degrees < 0) { - // Convert -90 to 270 and -180 to 180 - return degrees + 360; - } - // Output degrees in between [0, 360] - return degrees; -}; - -- (AVMutableVideoComposition *)getVideoCompositionWithTransform:(CGAffineTransform)transform - withAsset:(AVAsset *)asset - withVideoTrack:(AVAssetTrack *)videoTrack { - AVMutableVideoCompositionInstruction *instruction = - [AVMutableVideoCompositionInstruction videoCompositionInstruction]; - instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [asset duration]); - AVMutableVideoCompositionLayerInstruction *layerInstruction = - [AVMutableVideoCompositionLayerInstruction - videoCompositionLayerInstructionWithAssetTrack:videoTrack]; - [layerInstruction setTransform:_preferredTransform atTime:kCMTimeZero]; - - AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; - instruction.layerInstructions = @[ layerInstruction ]; - videoComposition.instructions = @[ instruction ]; - - // If in portrait mode, switch the width and height of the video - CGFloat width = videoTrack.naturalSize.width; - CGFloat height = videoTrack.naturalSize.height; - NSInteger rotationDegrees = - (NSInteger)round(radiansToDegrees(atan2(_preferredTransform.b, _preferredTransform.a))); - if (rotationDegrees == 90 || rotationDegrees == 270) { - width = videoTrack.naturalSize.height; - height = videoTrack.naturalSize.width; - } - videoComposition.renderSize = CGSizeMake(width, height); - - // TODO(@recastrodiaz): should we use videoTrack.nominalFrameRate ? - // Currently set at a constant 30 FPS - videoComposition.frameDuration = CMTimeMake(1, 30); - - return videoComposition; -} - -- (instancetype)initWithURL:(NSURL *)url - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink - httpHeaders:(nonnull NSDictionary *)headers - avFactory:(id)avFactory - registrar:(NSObject *)registrar { - NSDictionary *options = nil; - if ([headers count] != 0) { - options = @{@"AVURLAssetHTTPHeaderFieldsKey" : headers}; - } - AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:options]; - AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:urlAsset]; - return [self initWithPlayerItem:item - frameUpdater:frameUpdater - displayLink:(FVPDisplayLink *)displayLink - avFactory:avFactory - registrar:registrar]; -} - -- (instancetype)initWithPlayerItem:(AVPlayerItem *)item - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink - avFactory:(id)avFactory - registrar:(NSObject *)registrar { - self = [super init]; - NSAssert(self, @"super init cannot be nil"); - - _registrar = registrar; - _frameUpdater = frameUpdater; - - AVAsset *asset = [item asset]; - void (^assetCompletionHandler)(void) = ^{ - if ([asset statusOfValueForKey:@"tracks" error:nil] == AVKeyValueStatusLoaded) { - NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; - if ([tracks count] > 0) { - AVAssetTrack *videoTrack = tracks[0]; - void (^trackCompletionHandler)(void) = ^{ - if (self->_disposed) return; - if ([videoTrack statusOfValueForKey:@"preferredTransform" - error:nil] == AVKeyValueStatusLoaded) { - // Rotate the video by using a videoComposition and the preferredTransform - self->_preferredTransform = FVPGetStandardizedTransformForTrack(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 - // use with media served using HTTP Live Streaming. - AVMutableVideoComposition *videoComposition = - [self getVideoCompositionWithTransform:self->_preferredTransform - withAsset:asset - withVideoTrack:videoTrack]; - item.videoComposition = videoComposition; - } - }; - [videoTrack loadValuesAsynchronouslyForKeys:@[ @"preferredTransform" ] - completionHandler:trackCompletionHandler]; - } - } - }; - - _player = [avFactory playerWithPlayerItem:item]; - _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; - - // 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]; - [self.flutterViewLayer addSublayer:_playerLayer]; - - // Configure output. - _displayLink = displayLink; - NSDictionary *pixBuffAttributes = @{ - (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA), - (id)kCVPixelBufferIOSurfacePropertiesKey : @{} - }; - _videoOutput = [avFactory videoOutputWithPixelBufferAttributes:pixBuffAttributes]; - frameUpdater.videoOutput = _videoOutput; - - [self addObserversForItem:item player:_player]; - - [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:assetCompletionHandler]; - - return self; -} - -- (void)observeValueForKeyPath:(NSString *)path - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - if (context == timeRangeContext) { - if (_eventSink != nil) { - NSMutableArray *> *values = [[NSMutableArray alloc] init]; - for (NSValue *rangeValue in [object loadedTimeRanges]) { - CMTimeRange range = [rangeValue CMTimeRangeValue]; - int64_t start = FVPCMTimeToMillis(range.start); - [values addObject:@[ @(start), @(start + FVPCMTimeToMillis(range.duration)) ]]; - } - _eventSink(@{@"event" : @"bufferingUpdate", @"values" : values}); - } - } else if (context == statusContext) { - AVPlayerItem *item = (AVPlayerItem *)object; - switch (item.status) { - case AVPlayerItemStatusFailed: - [self sendFailedToLoadVideoEvent]; - break; - case AVPlayerItemStatusUnknown: - break; - case AVPlayerItemStatusReadyToPlay: - [item addOutput:_videoOutput]; - [self setupEventSinkIfReadyToPlay]; - [self updatePlayingState]; - break; - } - } else if (context == presentationSizeContext || context == durationContext) { - AVPlayerItem *item = (AVPlayerItem *)object; - if (item.status == AVPlayerItemStatusReadyToPlay) { - // 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 updatePlayingState]; - } - } else if (context == playbackLikelyToKeepUpContext) { - [self updatePlayingState]; - if ([[_player currentItem] isPlaybackLikelyToKeepUp]) { - if (_eventSink != nil) { - _eventSink(@{@"event" : @"bufferingEnd"}); - } - } else { - if (_eventSink != nil) { - _eventSink(@{@"event" : @"bufferingStart"}); - } - } - } else if (context == rateContext) { - // Important: Make sure to cast the object to AVPlayer when observing the rate property, - // as it is not available in AVPlayerItem. - AVPlayer *player = (AVPlayer *)object; - if (_eventSink != nil) { - _eventSink( - @{@"event" : @"isPlayingStateUpdate", @"isPlaying" : player.rate > 0 ? @YES : @NO}); - } - } -} - -- (void)updatePlayingState { - if (!_isInitialized) { - return; - } - if (_isPlaying) { - [_player play]; - } else { - [_player pause]; - } - // If the texture is still waiting for an expected frame, the display link needs to keep - // running until it arrives regardless of the play/pause state. - _displayLink.running = _isPlaying || self.waitingForFrame; -} - -- (void)sendFailedToLoadVideoEvent { - if (_eventSink == nil) { - return; - } - // 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) { - [details addObject:detail]; - } - }; - NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; - add(error.localizedDescription); - add(error.localizedFailureReason); - add(underlyingError.localizedDescription); - add(underlyingError.localizedFailureReason); - NSString *message = [details.array componentsJoinedByString:@": "]; - _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); -} - -- (void)setupEventSinkIfReadyToPlay { - if (_eventSink && !_isInitialized) { - AVPlayerItem *currentItem = self.player.currentItem; - CGSize size = currentItem.presentationSize; - CGFloat width = size.width; - CGFloat height = size.height; - - // Wait until tracks are loaded to check duration or if there are any videos. - AVAsset *asset = currentItem.asset; - if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { - void (^trackCompletionHandler)(void) = ^{ - if ([asset statusOfValueForKey:@"tracks" error:nil] != AVKeyValueStatusLoaded) { - // Cancelled, or something failed. - 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]; - return; - } - - BOOL hasVideoTracks = [asset tracksWithMediaType:AVMediaTypeVideo].count != 0; - BOOL hasNoTracks = asset.tracks.count == 0; - - // The player has not yet initialized when it has no size, unless it is an audio-only track. - // HLS m3u8 video files never load any tracks, and are also not yet initialized until they have - // a size. - if ((hasVideoTracks || hasNoTracks) && height == CGSizeZero.height && - width == CGSizeZero.width) { - return; - } - // The player may be initialized but still needs to determine the duration. - int64_t duration = [self duration]; - if (duration == 0) { - return; - } - - _isInitialized = YES; - _eventSink(@{ - @"event" : @"initialized", - @"duration" : @(duration), - @"width" : @(width), - @"height" : @(height) - }); - } -} - -- (void)play { - _isPlaying = YES; - [self updatePlayingState]; -} - -- (void)pause { - _isPlaying = NO; - [self updatePlayingState]; -} - -- (int64_t)position { - return FVPCMTimeToMillis([_player currentTime]); -} - -- (int64_t)duration { - // Note: https://openradar.appspot.com/radar?id=4968600712511488 - // `[AVPlayerItem duration]` can be `kCMTimeIndefinite`, - // use `[[AVPlayerItem asset] duration]` instead. - return FVPCMTimeToMillis([[[_player currentItem] asset] duration]); -} - -- (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { - CMTime previousCMTime = _player.currentTime; - CMTime targetCMTime = CMTimeMake(location, 1000); - CMTimeValue duration = _player.currentItem.asset.duration.value; - // Without adding tolerance when seeking to duration, - // seekToTime will never complete, and this call will hang. - // see issue https://github.com/flutter/flutter/issues/124475. - CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero; - [_player seekToTime:targetCMTime - toleranceBefore:tolerance - toleranceAfter:tolerance - completionHandler:^(BOOL completed) { - if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { - // Ensure that a frame is drawn once available, even if currently paused. In theory a race - // is possible here where the new frame has already drawn by the time this code runs, and - // the display link stays on indefinitely, but that should be relatively harmless. This - // must use the display link rather than just informing the engine that a new frame is - // available because the seek completing doesn't guarantee that the pixel buffer is - // already available. - [self expectFrame]; - } - - if (completionHandler) { - completionHandler(completed); - } - }]; -} - -- (void)expectFrame { - self.waitingForFrame = YES; - self.displayLink.running = YES; -} - -- (void)setIsLooping:(BOOL)isLooping { - _isLooping = isLooping; -} - -- (void)setVolume:(double)volume { - _player.volume = (float)((volume < 0.0) ? 0.0 : ((volume > 1.0) ? 1.0 : volume)); -} - -- (void)setPlaybackSpeed:(double)speed { - // See https://developer.apple.com/library/archive/qa/qa1772/_index.html for an explanation of - // these checks. - if (speed > 2.0 && !_player.currentItem.canPlayFastForward) { - if (_eventSink != nil) { - _eventSink([FlutterError errorWithCode:@"VideoError" - message:@"Video cannot be fast-forwarded beyond 2.0x" - details:nil]); - } - return; - } - - if (speed < 1.0 && !_player.currentItem.canPlaySlowForward) { - if (_eventSink != nil) { - _eventSink([FlutterError errorWithCode:@"VideoError" - message:@"Video cannot be slow-forwarded" - details:nil]); - } - return; - } - - _player.rate = speed; -} - -- (CVPixelBufferRef)copyPixelBuffer { - CVPixelBufferRef buffer = NULL; - CMTime outputItemTime = [_videoOutput itemTimeForHostTime:CACurrentMediaTime()]; - if ([_videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { - buffer = [_videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; - } else { - // If the current time isn't available yet, use the time that was checked when informing the - // engine that a frame was available (if any). - CMTime lastAvailableTime = self.frameUpdater.lastKnownAvailableTime; - if (CMTIME_IS_VALID(lastAvailableTime)) { - buffer = [_videoOutput copyPixelBufferForItemTime:lastAvailableTime itemTimeForDisplay:NULL]; - } - } - - if (self.waitingForFrame && buffer) { - self.waitingForFrame = NO; - // If the display link was only running temporarily to pick up a new frame while the video was - // paused, stop it again. - if (!self.isPlaying) { - self.displayLink.running = NO; - } - } - - return buffer; -} - -- (void)onTextureUnregistered:(NSObject *)texture { - dispatch_async(dispatch_get_main_queue(), ^{ - [self dispose]; - }); -} - -- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { - _eventSink = nil; - return nil; -} - -- (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments - eventSink:(nonnull FlutterEventSink)events { - _eventSink = events; - // TODO(@recastrodiaz): remove the line below when the race condition is resolved: - // https://github.com/flutter/flutter/issues/21483 - // This line ensures the 'initialized' event is sent when the event - // 'AVPlayerItemStatusReadyToPlay' fires before _eventSink is set (this function - // onListenWithArguments is called) - // 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]; - return nil; - } - [self setupEventSinkIfReadyToPlay]; - return nil; -} - -/// This method allows you to dispose without touching the event channel. This -/// is useful for the case where the Engine is in the process of deconstruction -/// so the channel is going to die or is already dead. -- (void)disposeSansEventChannel { - // This check prevents the crash caused by removing the KVO observers twice. - // When performing a Hot Restart, the leftover players are disposed once directly - // by [FVPVideoPlayerPlugin initialize:] method and then disposed again by - // [FVPVideoPlayer onTextureUnregistered:] call leading to possible over-release. - if (_disposed) { - return; - } - - _disposed = YES; - [_playerLayer removeFromSuperlayer]; - _displayLink = nil; - [self removeKeyValueObservers]; - - [self.player replaceCurrentItemWithPlayerItem:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)dispose { - [self disposeSansEventChannel]; - [_eventChannel setStreamHandler:nil]; -} - -- (CALayer *)flutterViewLayer { -#if TARGET_OS_OSX - return self.registrar.view.layer; -#else -#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 - UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; -#pragma clang diagnostic pop - return root.view.layer; -#endif -} - -/// Removes all key-value observers set up for the player. -/// -/// This is called from dealloc, so must not use any methods on self. -- (void)removeKeyValueObservers { - AVPlayerItem *currentItem = _player.currentItem; - [currentItem removeObserver:self forKeyPath:@"status"]; - [currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"]; - [currentItem removeObserver:self forKeyPath:@"presentationSize"]; - [currentItem removeObserver:self forKeyPath:@"duration"]; - [currentItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; - [_player removeObserver:self forKeyPath:@"rate"]; -} - -@end - @interface FVPVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject *registry; @property(readonly, weak, nonatomic) NSObject *messenger; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h new file mode 100644 index 00000000000..d6ee61c9d9a --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -0,0 +1,24 @@ +// 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. + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import + +@interface FVPFrameUpdater : NSObject +@property(nonatomic) int64_t textureId; +@property(nonatomic, weak, readonly) NSObject *registry; +// The output that this updater is managing. +@property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; +// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. +@property(nonatomic, assign) CMTime lastKnownAvailableTime; + +- (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry; + +- (void)displayLinkFired; +@end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h new file mode 100644 index 00000000000..69d01486f3f --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -0,0 +1,87 @@ +// 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. + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import +#import + +#import "FVPDisplayLink.h" +#import "FVPFrameUpdater.h" +#import "FVPVideoPlayerPlugin_Test.h" + +#pragma mark - + +@interface FVPVideoPlayer () +@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; +// The plugin registrar, to obtain view information from. +@property(nonatomic, weak) NSObject *registrar; +// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly) CALayer *flutterViewLayer; +@property(nonatomic) FlutterEventChannel *eventChannel; +@property(nonatomic) FlutterEventSink eventSink; +@property(nonatomic) CGAffineTransform preferredTransform; +@property(nonatomic, readonly) BOOL disposed; +@property(nonatomic, readonly) BOOL isPlaying; +@property(nonatomic) BOOL isLooping; +@property(nonatomic, readonly) BOOL isInitialized; +// The updater that drives callbacks to the engine to indicate that a new frame is ready. +@property(nonatomic) FVPFrameUpdater *frameUpdater; +// The display link that drives frameUpdater. +@property(nonatomic) FVPDisplayLink *displayLink; +// Whether a new frame needs to be provided to the engine regardless of the current play/pause state +// (e.g., after a seek while paused). If YES, the display link should continue to run until the next +// frame is successfully provided. +@property(nonatomic, assign) BOOL waitingForFrame; + +- (instancetype)initWithURL:(NSURL *)url + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:(nonnull NSDictionary *)headers + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +- (instancetype)initWithURL:(NSURL *)url + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:(nonnull NSDictionary *)headers + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +- (instancetype)initWithAsset:(AVPlayerItem *)item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +- (void)updatePlayingState; + +- (void)dispose; + +- (void)disposeSansEventChannel; + +- (void)setVolume:(double)volume; + +- (void)setPlaybackSpeed:(double)speed; + +- (void)play; + +- (void)pause; + +- (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler; + +// Tells the player to run its frame updater until it receives a frame, regardless of the +// play/pause state. +- (void)expectFrame; +@end \ No newline at end of file From a2d3d9f2ad56ad9a13bf6d9e6c4d1e3fdb0e5292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 16:54:56 +0100 Subject: [PATCH 002/167] Add docs for FVPFrameUpdater and FVPVideoPlayer interfaces --- .../FVPVideoPlayer.m | 3 -- .../FVPFrameUpdater.h | 11 +++- .../FVPVideoPlayer.h | 52 +++++++++++++------ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index c9df951f4c0..5ea2c54625e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -520,9 +520,6 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments return nil; } -/// This method allows you to dispose without touching the event channel. This -/// is useful for the case where the Engine is in the process of deconstruction -/// so the channel is going to die or is already dead. - (void)disposeSansEventChannel { // This check prevents the crash caused by removing the KVO observers twice. // When performing a Hot Restart, the leftover players are disposed once directly diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index d6ee61c9d9a..5fced39a1b1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -10,15 +10,22 @@ #import +/// FVPFrameUpdater is responsible for notifying the Flutter texture registry +/// when a new video frame is available. @interface FVPFrameUpdater : NSObject +/// The texture ID associated with the video output. @property(nonatomic) int64_t textureId; +/// The Flutter texture registry used to notify about new frames. @property(nonatomic, weak, readonly) NSObject *registry; -// The output that this updater is managing. +/// The output that this updater is managing. @property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; -// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. +/// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. @property(nonatomic, assign) CMTime lastKnownAvailableTime; +/// Initializes a new instance of FVPFrameUpdater with the given Flutter texture registry. - (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry; +/// Called when the display link fires. Checks if a new frame is available +/// and notifies the Flutter texture registry if a new frame is found. - (void)displayLinkFired; @end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 69d01486f3f..9127fb77945 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -17,28 +17,41 @@ #pragma mark - +/// FVPVideoPlayer is responsible for managing video playback using AVPlayer. +/// It provides methods to control playback, adjust volume, handle seeking, and +/// notify the Flutter engine about new video frames. @interface FVPVideoPlayer () +/// The AVPlayerItemVideoOutput associated with this video player. @property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; -// The plugin registrar, to obtain view information from. +/// The plugin registrar, to obtain view information from. @property(nonatomic, weak) NSObject *registrar; -// The CALayer associated with the Flutter view this plugin is associated with, if any. +/// The CALayer associated with the Flutter view this plugin is associated with, if any. @property(nonatomic, readonly) CALayer *flutterViewLayer; +/// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; +/// The Flutter event sink used to send events to the Flutter engine. @property(nonatomic) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. @property(nonatomic) CGAffineTransform preferredTransform; +/// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; +/// Indicates whether the video player is currently playing. @property(nonatomic, readonly) BOOL isPlaying; +/// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; +/// Indicates whether the video player has been initialized. @property(nonatomic, readonly) BOOL isInitialized; -// The updater that drives callbacks to the engine to indicate that a new frame is ready. +/// The updater that drives callbacks to the engine to indicate that a new frame is ready. @property(nonatomic) FVPFrameUpdater *frameUpdater; -// The display link that drives frameUpdater. +/// The display link that drives frameUpdater. @property(nonatomic) FVPDisplayLink *displayLink; -// Whether a new frame needs to be provided to the engine regardless of the current play/pause state -// (e.g., after a seek while paused). If YES, the display link should continue to run until the next -// frame is successfully provided. +/// Whether a new frame needs to be provided to the engine regardless of the current play/pause +/// state (e.g., after a seek while paused). If YES, the display link should continue to run until +/// the next frame is successfully provided. @property(nonatomic, assign) BOOL waitingForFrame; +/// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, +/// HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink @@ -46,42 +59,49 @@ avFactory:(id)avFactory registrar:(NSObject *)registrar; -- (instancetype)initWithURL:(NSURL *)url - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink - httpHeaders:(nonnull NSDictionary *)headers - avFactory:(id)avFactory - registrar:(NSObject *)registrar; - +/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display +/// link, AV factory, and registrar. - (instancetype)initWithPlayerItem:(AVPlayerItem *)item frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar; +/// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, +/// AV factory, and registrar. - (instancetype)initWithAsset:(AVPlayerItem *)item frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar; +/// Updates the playing state of the video player. - (void)updatePlayingState; +/// Disposes the video player and releases any resources it holds. - (void)dispose; +/// Disposes the video player without touching the event channel. This +/// is useful for the case where the Engine is in the process of deconstruction +/// so the channel is going to die or is already dead. - (void)disposeSansEventChannel; +/// Sets the volume of the video player. - (void)setVolume:(double)volume; +/// Sets the playback speed of the video player. - (void)setPlaybackSpeed:(double)speed; +/// Starts playing the video. - (void)play; +/// Pauses the video. - (void)pause; +/// Seeks to the specified location in the video and calls the completion handler when done. - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler; -// Tells the player to run its frame updater until it receives a frame, regardless of the -// play/pause state. +/// Tells the player to run its frame updater until it receives a frame, regardless of the +/// play/pause state. - (void)expectFrame; @end \ No newline at end of file From a74c720bd5670632a66b03071efeef88634cbd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 17:41:55 +0100 Subject: [PATCH 003/167] Remove unused imports and #pragma statements --- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 2 -- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 2 -- .../include/video_player_avfoundation/FVPVideoPlayer.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 5ea2c54625e..58842c697bd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -5,8 +5,6 @@ #import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/AVAssetTrackUtils.h" -#pragma mark - - static void *timeRangeContext = &timeRangeContext; static void *statusContext = &statusContext; static void *presentationSizeContext = &presentationSizeContext; 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 fbca6e02a4e..ee34f86eaf3 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 @@ -3,11 +3,9 @@ // found in the LICENSE file. #import "FVPVideoPlayerPlugin.h" -#import "FVPVideoPlayerPlugin_Test.h" #import -#import "./include/video_player_avfoundation/AVAssetTrackUtils.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 9127fb77945..ec005a82017 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -15,8 +15,6 @@ #import "FVPFrameUpdater.h" #import "FVPVideoPlayerPlugin_Test.h" -#pragma mark - - /// FVPVideoPlayer is responsible for managing video playback using AVPlayer. /// It provides methods to control playback, adjust volume, handle seeking, and /// notify the Flutter engine about new video frames. From 9092b711f341506d281cb1f38f79598048671348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 17:42:05 +0100 Subject: [PATCH 004/167] Add empty lines at the end of files --- .../include/video_player_avfoundation/FVPFrameUpdater.h | 2 +- .../include/video_player_avfoundation/FVPVideoPlayer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index 5fced39a1b1..a0a9627f72f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -28,4 +28,4 @@ /// Called when the display link fires. Checks if a new frame is available /// and notifies the Flutter texture registry if a new frame is found. - (void)displayLinkFired; -@end \ No newline at end of file +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index ec005a82017..22bc336fa23 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -102,4 +102,4 @@ /// Tells the player to run its frame updater until it receives a frame, regardless of the /// play/pause state. - (void)expectFrame; -@end \ No newline at end of file +@end From add5719f1f25750b1a354bb26faa033a8112346b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 18:17:13 +0100 Subject: [PATCH 005/167] Bump version to 2.6.4 and update changelog --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 4 ++++ packages/video_player/video_player_avfoundation/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index fe47d79e6a6..78e81641042 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.6.4 + +* Extracts `FVPVideoPlayer` and `FVPFrameUpdater` from the `FVPVideoPlayerPlugin.m` file and places them into separate files. + ## 2.6.3 * Fixes VideoPlayerController.initialize() future never resolving with invalid video file. diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 31d615dd886..233a9b65e86 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.3 +version: 2.6.4 environment: sdk: ^3.3.0 From 9587ad04dea30a3ef103b681657bfc32f068659b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 18:23:05 +0100 Subject: [PATCH 006/167] Move GLKit import from header file to source file --- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 4 +++- .../include/video_player_avfoundation/FVPVideoPlayer.h | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 58842c697bd..61d737b868c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "./include/video_player_avfoundation/FVPVideoPlayer.h" +#import + #import "./include/video_player_avfoundation/AVAssetTrackUtils.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer.h" static void *timeRangeContext = &timeRangeContext; static void *statusContext = &statusContext; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 22bc336fa23..d43e744e57b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -9,7 +9,6 @@ #endif #import -#import #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" From 83cec0c802706ab2036d7e227a514afcf13fc267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 22 Nov 2024 11:47:14 +0100 Subject: [PATCH 007/167] Add FVPVideoPlayerPlugin_Test import to plugin file --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 1 + 1 file changed, 1 insertion(+) 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 ee34f86eaf3..f864bc06cbc 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 @@ -9,6 +9,7 @@ #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" +#import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" #import "./include/video_player_avfoundation/messages.g.h" #if !__has_feature(objc_arc) From 99123db46428a636de4f865a9ddb37828598a8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 22 Nov 2024 11:51:47 +0100 Subject: [PATCH 008/167] Fix parameter type in interface constructor --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 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/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index d43e744e57b..9fa875e4337 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -66,7 +66,7 @@ /// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, /// AV factory, and registrar. -- (instancetype)initWithAsset:(AVPlayerItem *)item +- (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory From 9545fda07190008c3a7d044ad7b174ea3960712a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 25 Nov 2024 10:27:57 +0100 Subject: [PATCH 009/167] Separate plugin and factory classes by pragma mark --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 2 ++ 1 file changed, 2 insertions(+) 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 f864bc06cbc..cc81b3e6dd7 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 @@ -41,6 +41,8 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr @end +#pragma mark - + @interface FVPVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject *registry; @property(readonly, weak, nonatomic) NSObject *messenger; From 75b5ab93a219f13451c39535550e7dfcb8a5bc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 25 Nov 2024 13:12:37 +0100 Subject: [PATCH 010/167] Add nullability type specifiers to FVPVideoPlayer interface --- .../FVPVideoPlayer.h | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 9fa875e4337..3cb94b4b74c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -19,15 +19,15 @@ /// notify the Flutter engine about new video frames. @interface FVPVideoPlayer () /// The AVPlayerItemVideoOutput associated with this video player. -@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; +@property(readonly, nonatomic, nonnull) AVPlayerItemVideoOutput *videoOutput; /// The plugin registrar, to obtain view information from. -@property(nonatomic, weak) NSObject *registrar; +@property(nonatomic, weak, nullable) NSObject *registrar; /// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly) CALayer *flutterViewLayer; +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; /// The Flutter event channel used to communicate with the Flutter engine. -@property(nonatomic) FlutterEventChannel *eventChannel; +@property(nonatomic, nonnull) FlutterEventChannel *eventChannel; /// The Flutter event sink used to send events to the Flutter engine. -@property(nonatomic) FlutterEventSink eventSink; +@property(nonatomic, nonnull) FlutterEventSink eventSink; /// The preferred transform for the video. It can be used to handle the rotation of the video. @property(nonatomic) CGAffineTransform preferredTransform; /// Indicates whether the video player has been disposed. @@ -39,14 +39,16 @@ /// Indicates whether the video player has been initialized. @property(nonatomic, readonly) BOOL isInitialized; /// The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic) FVPFrameUpdater *frameUpdater; +@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; /// The display link that drives frameUpdater. -@property(nonatomic) FVPDisplayLink *displayLink; +@property(nonatomic, nullable) FVPDisplayLink *displayLink; /// Whether a new frame needs to be provided to the engine regardless of the current play/pause /// state (e.g., after a seek while paused). If YES, the display link should continue to run until /// the next frame is successfully provided. @property(nonatomic, assign) BOOL waitingForFrame; +NS_ASSUME_NONNULL_BEGIN + /// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, /// HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url @@ -72,6 +74,8 @@ avFactory:(id)avFactory registrar:(NSObject *)registrar; +NS_ASSUME_NONNULL_END + /// Updates the playing state of the video player. - (void)updatePlayingState; @@ -95,8 +99,9 @@ /// Pauses the video. - (void)pause; -/// Seeks to the specified location in the video and calls the completion handler when done. -- (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler; +/// Seeks to the specified location in the video and calls the completion handler when done, if one +/// is supplied. +- (void)seekTo:(int64_t)location completionHandler:(void (^_Nullable)(BOOL))completionHandler; /// Tells the player to run its frame updater until it receives a frame, regardless of the /// play/pause state. From 5ec766f11b1f8614015e090b8fbe87d3378341fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 2 Dec 2024 10:55:56 +0100 Subject: [PATCH 011/167] Make properties not needed in header of FVPVideoPlayer private --- .../FVPVideoPlayer.m | 25 +++++++++++++++++++ .../FVPVideoPlayer.h | 22 ---------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 61d737b868c..ded2004deb1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -14,6 +14,31 @@ static void *playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext; static void *rateContext = &rateContext; +@interface FVPVideoPlayer () +/// The AVPlayerItemVideoOutput associated with this video player. +@property(readonly, nonatomic, nonnull) AVPlayerItemVideoOutput *videoOutput; +/// The plugin registrar, to obtain view information from. +@property(nonatomic, readonly) NSObject *registrar; +/// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; +/// The Flutter event sink used to send events to the Flutter engine. +@property(nonatomic, nonnull) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. +@property(nonatomic) CGAffineTransform preferredTransform; +/// Indicates whether the video player is currently playing. +@property(nonatomic, readonly) BOOL isPlaying; +/// Indicates whether the video player has been initialized. +@property(nonatomic, readonly) BOOL isInitialized; +/// The updater that drives callbacks to the engine to indicate that a new frame is ready. +@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; +/// The display link that drives frameUpdater. +@property(nonatomic, nullable) FVPDisplayLink *displayLink; +/// Whether a new frame needs to be provided to the engine regardless of the current play/pause +/// state (e.g., after a seek while paused). If YES, the display link should continue to run until +/// the next frame is successfully provided. +@property(nonatomic, assign) BOOL waitingForFrame; +@end + @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 3cb94b4b74c..b67483ce5cb 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -18,34 +18,12 @@ /// It provides methods to control playback, adjust volume, handle seeking, and /// notify the Flutter engine about new video frames. @interface FVPVideoPlayer () -/// The AVPlayerItemVideoOutput associated with this video player. -@property(readonly, nonatomic, nonnull) AVPlayerItemVideoOutput *videoOutput; -/// The plugin registrar, to obtain view information from. -@property(nonatomic, weak, nullable) NSObject *registrar; -/// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic, nonnull) FlutterEventChannel *eventChannel; -/// The Flutter event sink used to send events to the Flutter engine. -@property(nonatomic, nonnull) FlutterEventSink eventSink; -/// The preferred transform for the video. It can be used to handle the rotation of the video. -@property(nonatomic) CGAffineTransform preferredTransform; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; -/// Indicates whether the video player is currently playing. -@property(nonatomic, readonly) BOOL isPlaying; /// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; -/// Indicates whether the video player has been initialized. -@property(nonatomic, readonly) BOOL isInitialized; -/// The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; -/// The display link that drives frameUpdater. -@property(nonatomic, nullable) FVPDisplayLink *displayLink; -/// Whether a new frame needs to be provided to the engine regardless of the current play/pause -/// state (e.g., after a seek while paused). If YES, the display link should continue to run until -/// the next frame is successfully provided. -@property(nonatomic, assign) BOOL waitingForFrame; NS_ASSUME_NONNULL_BEGIN From c958a4a538d4e5b6692a0255ca0b55d9ddda7d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 2 Dec 2024 11:01:11 +0100 Subject: [PATCH 012/167] Use nonnull macro for the whole header file --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index b67483ce5cb..ed3226a0c8c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -14,19 +14,19 @@ #import "FVPFrameUpdater.h" #import "FVPVideoPlayerPlugin_Test.h" +NS_ASSUME_NONNULL_BEGIN + /// FVPVideoPlayer is responsible for managing video playback using AVPlayer. /// It provides methods to control playback, adjust volume, handle seeking, and /// notify the Flutter engine about new video frames. @interface FVPVideoPlayer () /// The Flutter event channel used to communicate with the Flutter engine. -@property(nonatomic, nonnull) FlutterEventChannel *eventChannel; +@property(nonatomic) FlutterEventChannel *eventChannel; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; -NS_ASSUME_NONNULL_BEGIN - /// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, /// HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url @@ -52,8 +52,6 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; -NS_ASSUME_NONNULL_END - /// Updates the playing state of the video player. - (void)updatePlayingState; @@ -85,3 +83,5 @@ NS_ASSUME_NONNULL_END /// play/pause state. - (void)expectFrame; @end + +NS_ASSUME_NONNULL_END From 0a707a55670521dc5b401244ca4e8642e3627b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 2 Dec 2024 11:58:34 +0100 Subject: [PATCH 013/167] Make updatePlayingState private for FVPVideoPlayer --- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 3 +++ .../include/video_player_avfoundation/FVPVideoPlayer.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index ded2004deb1..8ee6d71c2a1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -37,6 +37,9 @@ @interface FVPVideoPlayer () /// state (e.g., after a seek while paused). If YES, the display link should continue to run until /// the next frame is successfully provided. @property(nonatomic, assign) BOOL waitingForFrame; + +/// Updates the playing state of the video player. +- (void)updatePlayingState; @end @implementation FVPVideoPlayer diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index ed3226a0c8c..ed3de857b82 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -52,9 +52,6 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Updates the playing state of the video player. -- (void)updatePlayingState; - /// Disposes the video player and releases any resources it holds. - (void)dispose; From 0055ea3bff67a060e66b1f580e79f546e5c21c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 2 Dec 2024 11:58:49 +0100 Subject: [PATCH 014/167] Make texture registry private for FVPFrameUpdater --- .../Sources/video_player_avfoundation/FVPFrameUpdater.m | 7 +++++++ .../include/video_player_avfoundation/FVPFrameUpdater.h | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m index 42f5e1dc743..435699879f1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m @@ -4,6 +4,13 @@ #import "./include/video_player_avfoundation/FVPFrameUpdater.h" +/// FVPFrameUpdater is responsible for notifying the Flutter texture registry +/// when a new video frame is available. +@interface FVPFrameUpdater () +/// The Flutter texture registry used to notify about new frames. +@property(nonatomic, weak, readonly) NSObject *registry; +@end + @implementation FVPFrameUpdater - (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry { NSAssert(self, @"super init cannot be nil"); diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index a0a9627f72f..92686202833 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -15,8 +15,6 @@ @interface FVPFrameUpdater : NSObject /// The texture ID associated with the video output. @property(nonatomic) int64_t textureId; -/// The Flutter texture registry used to notify about new frames. -@property(nonatomic, weak, readonly) NSObject *registry; /// The output that this updater is managing. @property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; /// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. From 717315e53ead6125174e5da3bb9210f55a5b8d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 2 Dec 2024 14:34:24 +0100 Subject: [PATCH 015/167] Move code from Plugin_Test file to different files --- .../video_player_avfoundation/FVPAVFactory.m | 17 ++++++++++ .../FVPVideoPlayerPlugin.m | 14 +-------- .../video_player_avfoundation/FVPAVFactory.h | 21 +++++++++++++ .../FVPVideoPlayer.h | 18 +++++++++-- .../FVPVideoPlayerPlugin_Test.h | 31 ++----------------- 5 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPAVFactory.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPAVFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPAVFactory.m new file mode 100644 index 00000000000..f102235e238 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPAVFactory.m @@ -0,0 +1,17 @@ +// 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 + +#import "FVPAVFactory.h" + +@implementation FVPDefaultAVFactory +- (AVPlayer *)playerWithPlayerItem:(AVPlayerItem *)playerItem { + return [AVPlayer playerWithPlayerItem:playerItem]; +} +- (AVPlayerItemVideoOutput *)videoOutputWithPixelBufferAttributes: + (NSDictionary *)attributes { + return [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:attributes]; +} +@end 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 cc81b3e6dd7..b712b0b34a5 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 @@ -6,6 +6,7 @@ #import +#import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" @@ -16,19 +17,6 @@ #error Code Requires ARC. #endif -@interface FVPDefaultAVFactory : NSObject -@end - -@implementation FVPDefaultAVFactory -- (AVPlayer *)playerWithPlayerItem:(AVPlayerItem *)playerItem { - return [AVPlayer playerWithPlayerItem:playerItem]; -} -- (AVPlayerItemVideoOutput *)videoOutputWithPixelBufferAttributes: - (NSDictionary *)attributes { - return [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:attributes]; -} -@end - /// Non-test implementation of the diplay link factory. @interface FVPDefaultDisplayLinkFactory : NSObject @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h new file mode 100644 index 00000000000..0dabc41a880 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h @@ -0,0 +1,21 @@ +// 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 + +/// Protocol for AVFoundation object instance factory. Used for injecting framework objects in +/// tests. +@protocol FVPAVFactory +/// Creates and returns an AVPlayer instance with the specified AVPlayerItem. +@required +- (AVPlayer *)playerWithPlayerItem:(AVPlayerItem *)playerItem; + +/// Creates and returns an AVPlayerItemVideoOutput instance with the specified pixel buffer +/// attributes. +- (AVPlayerItemVideoOutput *)videoOutputWithPixelBufferAttributes: + (NSDictionary *)attributes; +@end + +@interface FVPDefaultAVFactory : NSObject +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index ed3de857b82..4950e58f144 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -10,22 +10,32 @@ #import +#import "FVPAVFactory.h" #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" -#import "FVPVideoPlayerPlugin_Test.h" NS_ASSUME_NONNULL_BEGIN /// FVPVideoPlayer is responsible for managing video playback using AVPlayer. /// It provides methods to control playback, adjust volume, handle seeking, and /// notify the Flutter engine about new video frames. -@interface FVPVideoPlayer () +@interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; +/// The AVPlayer instance used for video playback. +@property(readonly, nonatomic, nonnull) AVPlayer *player; +// 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(nonatomic, nonnull) AVPlayerLayer *playerLayer; +/// The current playback position of the video, in milliseconds. +@property(readonly, nonatomic) int64_t position; /// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, /// HTTP headers, AV factory, and registrar. @@ -79,6 +89,10 @@ NS_ASSUME_NONNULL_BEGIN /// Tells the player to run its frame updater until it receives a frame, regardless of the /// play/pause state. - (void)expectFrame; + +/// Called when the texture is unregistered. +/// This method is used to clean up resources associated with the texture. +- (void)onTextureUnregistered:(nullable NSObject *)texture; @end NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h index e34ce16eabc..e045210e68c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h @@ -2,21 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FVPVideoPlayerPlugin.h" - -#import - +#import "FVPAVFactory.h" #import "FVPDisplayLink.h" +#import "FVPVideoPlayer.h" +#import "FVPVideoPlayerPlugin.h" #import "messages.g.h" -// Protocol for AVFoundation object instance factory. Used for injecting framework objects in tests. -@protocol FVPAVFactory -@required -- (AVPlayer *)playerWithPlayerItem:(AVPlayerItem *)playerItem; -- (AVPlayerItemVideoOutput *)videoOutputWithPixelBufferAttributes: - (NSDictionary *)attributes; -@end - // Protocol for an AVPlayer instance factory. Used for injecting display links in tests. @protocol FVPDisplayLinkFactory - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registrar @@ -25,22 +16,6 @@ #pragma mark - -// TODO(stuartmorgan): Move this whole class to its own files. -@interface FVPVideoPlayer : NSObject -@property(readonly, nonatomic) AVPlayer *player; -// 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) int64_t position; - -- (void)onTextureUnregistered:(NSObject *)texture; -@end - -#pragma mark - - @interface FVPVideoPlayerPlugin () @property(readonly, strong, nonatomic) From 489f2a94409667854f907798d3d12b052db069b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 09:59:21 +0100 Subject: [PATCH 016/167] Make changelog description more general --- 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 78e81641042..55d1435a118 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.6.4 -* Extracts `FVPVideoPlayer` and `FVPFrameUpdater` from the `FVPVideoPlayerPlugin.m` file and places them into separate files. +* Refactors native code structure. ## 2.6.3 From 599adc89cb80026ea9f51e153f3fb82f80a44668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 10:36:49 +0100 Subject: [PATCH 017/167] Add a doc comment for FVPDefaultAVFactory --- .../include/video_player_avfoundation/FVPAVFactory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h index 0dabc41a880..a9c6ad5c011 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPAVFactory.h @@ -17,5 +17,6 @@ (NSDictionary *)attributes; @end +/// A default implementation of the FVPAVFactory protocol. @interface FVPDefaultAVFactory : NSObject @end From 513961c7a0bafac7c705bc204d0deb2a747bd455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 10:57:04 +0100 Subject: [PATCH 018/167] Make lastKnownAvailableTime property of FVPFrameUpdater readonly --- .../include/video_player_avfoundation/FVPFrameUpdater.h | 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/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index 92686202833..ac8e46578f2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -18,7 +18,7 @@ /// The output that this updater is managing. @property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; /// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. -@property(nonatomic, assign) CMTime lastKnownAvailableTime; +@property(readonly, nonatomic, assign) CMTime lastKnownAvailableTime; /// Initializes a new instance of FVPFrameUpdater with the given Flutter texture registry. - (FVPFrameUpdater *)initWithRegistry:(NSObject *)registry; From ff11b63d68a194c5b0558f016562f855f4f3f481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 12:36:56 +0100 Subject: [PATCH 019/167] Add _Test.h file for FVPVideoPlayer --- .../FVPVideoPlayer.m | 2 +- .../FVPVideoPlayerPlugin.m | 2 +- .../FVPVideoPlayer.h | 14 +-------- .../FVPVideoPlayer_Test.h | 31 +++++++++++++++++++ 4 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 8ee6d71c2a1..31db6221d94 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -5,7 +5,7 @@ #import #import "./include/video_player_avfoundation/AVAssetTrackUtils.h" -#import "./include/video_player_avfoundation/FVPVideoPlayer.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" static void *timeRangeContext = &timeRangeContext; static void *statusContext = &statusContext; 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 b712b0b34a5..38ece4a1c34 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 @@ -9,8 +9,8 @@ #import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" -#import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" #import "./include/video_player_avfoundation/messages.g.h" #if !__has_feature(objc_arc) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 4950e58f144..b8e66c22ce8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -19,21 +19,13 @@ NS_ASSUME_NONNULL_BEGIN /// FVPVideoPlayer is responsible for managing video playback using AVPlayer. /// It provides methods to control playback, adjust volume, handle seeking, and /// notify the Flutter engine about new video frames. -@interface FVPVideoPlayer : NSObject +@interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; -/// The AVPlayer instance used for video playback. -@property(readonly, nonatomic, nonnull) AVPlayer *player; -// 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(nonatomic, nonnull) AVPlayerLayer *playerLayer; /// The current playback position of the video, in milliseconds. @property(readonly, nonatomic) int64_t position; @@ -89,10 +81,6 @@ NS_ASSUME_NONNULL_BEGIN /// Tells the player to run its frame updater until it receives a frame, regardless of the /// play/pause state. - (void)expectFrame; - -/// Called when the texture is unregistered. -/// This method is used to clean up resources associated with the texture. -- (void)onTextureUnregistered:(nullable NSObject *)texture; @end NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h new file mode 100644 index 00000000000..4d6717b76d2 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h @@ -0,0 +1,31 @@ +// 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. + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import "FVPVideoPlayer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FVPVideoPlayer () +/// The AVPlayer instance used for video playback. +@property(readonly, nonatomic) AVPlayer *player; +/// The AVPlayerLayer used to display the video content. +/// 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; + +/// Called when the texture is unregistered. +/// This method is used to clean up resources associated with the texture. +- (void)onTextureUnregistered:(nullable NSObject *)texture; +@end + +NS_ASSUME_NONNULL_END From 12efd58a2409c4592417d7039cca0011efd2ddfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 18 Nov 2024 15:15:36 +0100 Subject: [PATCH 020/167] Add FVPNativeVideoViewFactory and FVPNativeVideoView (everything in one file for now) --- .../FVPVideoPlayerPlugin.m | 4 ++++ .../FVPVideoPlayerPlugin.h | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) 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 38ece4a1c34..8a32dc7717d 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 @@ -43,6 +43,10 @@ @implementation FVPVideoPlayerPlugin + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; + FVPNativeVideoViewFactory *factory = + [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger + playersByTextureId:instance.playersByTextureId]; + [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h index b64a173fe0c..9e2f3028939 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h @@ -8,6 +8,22 @@ #import #endif +#import + @interface FVPVideoPlayerPlugin : NSObject - (instancetype)initWithRegistrar:(NSObject *)registrar; @end + +@interface FVPNativeVideoViewFactory : NSObject +- (instancetype)initWithMessenger:(NSObject *)messenger; +@end + +@interface FVPNativeVideoView : NSObject +- (instancetype)initWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args + binaryMessenger:(NSObject *)messenger + player:(AVPlayer *)player; + +- (UIView *)view; +@end From 42c3724c867287f71346f5bd0479d87f58a3c9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 18 Nov 2024 15:16:20 +0100 Subject: [PATCH 021/167] Use platform view in Dart Code (hardcoded) --- .../lib/src/avfoundation_video_player.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index ace8f749a6b..b964d5e38f5 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -141,6 +141,21 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Widget buildView(int textureId) { + // FIXME Use platform view or texture view based on a param. + // FIXME Use a separate class for creation. + + final Map creationParams = { + 'viewId': textureId, + }; + return IgnorePointer( + // IgnorePointer so that GestureDetector can be used above the platform view. + child: UiKitView( + viewType: 'plugins.flutter.dev/video_player_ios', + creationParams: creationParams, + creationParamsCodec: const StandardMessageCodec(), + ), + ); + return Texture(textureId: textureId); } From 968bbf19237a00f01518c1e3ec5d19f2817ba8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 18 Nov 2024 15:54:32 +0100 Subject: [PATCH 022/167] Add PlatformVideoViewType enum to allow choosing between texture view and platform view for each video --- .../video_player_avfoundation/messages.g.h | 64 ++--- .../video_player_avfoundation/messages.g.m | 225 +++++++-------- .../lib/src/avfoundation_video_player.dart | 41 ++- .../lib/src/messages.g.dart | 126 ++++----- .../pigeons/messages.dart | 8 + .../test/test_api.g.dart | 257 ++++++------------ .../lib/video_player_platform_interface.dart | 10 +- 7 files changed, 319 insertions(+), 412 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h index afb118f14cd..81c227e3c13 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h @@ -1,7 +1,7 @@ // 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. -// Autogenerated from Pigeon (v22.4.2), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon #import @@ -13,21 +13,35 @@ NS_ASSUME_NONNULL_BEGIN +/// Pigeon equivalent of VideoViewType. +typedef NS_ENUM(NSUInteger, FVPPlatformVideoViewType) { + FVPPlatformVideoViewTypeTextureView = 0, + FVPPlatformVideoViewTypePlatformView = 1, +}; + +/// Wrapper for FVPPlatformVideoViewType to allow for nullability. +@interface FVPPlatformVideoViewTypeBox : NSObject +@property(nonatomic, assign) FVPPlatformVideoViewType value; +- (instancetype)initWithValue:(FVPPlatformVideoViewType)value; +@end + @class FVPCreationOptions; @interface FVPCreationOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders; -@property(nonatomic, copy, nullable) NSString *asset; -@property(nonatomic, copy, nullable) NSString *uri; -@property(nonatomic, copy, nullable) NSString *packageName; -@property(nonatomic, copy, nullable) NSString *formatHint; -@property(nonatomic, copy) NSDictionary *httpHeaders; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType; +@property(nonatomic, copy, nullable) NSString * asset; +@property(nonatomic, copy, nullable) NSString * uri; +@property(nonatomic, copy, nullable) NSString * packageName; +@property(nonatomic, copy, nullable) NSString * formatHint; +@property(nonatomic, copy) NSDictionary * httpHeaders; +@property(nonatomic, strong, nullable) FVPPlatformVideoViewTypeBox * viewType; @end /// The codec used by all APIs. @@ -36,35 +50,21 @@ NSObject *FVPGetMessagesCodec(void); @protocol FVPAVFoundationVideoPlayerApi - (void)initialize:(FlutterError *_Nullable *_Nonnull)error; /// @return `nil` only when `error != nil`. -- (nullable NSNumber *)createWithOptions:(FVPCreationOptions *)creationOptions - error:(FlutterError *_Nullable *_Nonnull)error; +- (nullable NSNumber *)createWithOptions:(FVPCreationOptions *)creationOptions error:(FlutterError *_Nullable *_Nonnull)error; - (void)disposePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setLooping:(BOOL)isLooping - forPlayer:(NSInteger)textureId - error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setVolume:(double)volume - forPlayer:(NSInteger)textureId - error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setPlaybackSpeed:(double)speed - forPlayer:(NSInteger)textureId - error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setVolume:(double)volume forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setPlaybackSpeed:(double)speed forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; - (void)playPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; /// @return `nil` only when `error != nil`. -- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId - error:(FlutterError *_Nullable *_Nonnull)error; -- (void)seekTo:(NSInteger)position - forPlayer:(NSInteger)textureId - completion:(void (^)(FlutterError *_Nullable))completion; +- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)seekTo:(NSInteger)position forPlayer:(NSInteger)textureId completion:(void (^)(FlutterError *_Nullable))completion; - (void)pausePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setMixWithOthers:(BOOL)mixWithOthers error:(FlutterError *_Nullable *_Nonnull)error; @end -extern void SetUpFVPAVFoundationVideoPlayerApi( - id binaryMessenger, - NSObject *_Nullable api); +extern void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *_Nullable api); -extern void SetUpFVPAVFoundationVideoPlayerApiWithSuffix( - id binaryMessenger, - NSObject *_Nullable api, NSString *messageChannelSuffix); +extern void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *_Nullable api, NSString *messageChannelSuffix); NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index 9749b125a9e..c26cfb0227f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -1,7 +1,7 @@ // 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. -// Autogenerated from Pigeon (v22.4.2), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon #import "./include/video_player_avfoundation/messages.g.h" @@ -30,6 +30,17 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { return (result == [NSNull null]) ? nil : result; } +/// Pigeon equivalent of VideoViewType. +@implementation FVPPlatformVideoViewTypeBox +- (instancetype)initWithValue:(FVPPlatformVideoViewType)value { + self = [super init]; + if (self) { + _value = value; + } + return self; +} +@end + @interface FVPCreationOptions () + (FVPCreationOptions *)fromList:(NSArray *)list; + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list; @@ -38,16 +49,18 @@ + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list; @implementation FVPCreationOptions + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders { - FVPCreationOptions *pigeonResult = [[FVPCreationOptions alloc] init]; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { + FVPCreationOptions* pigeonResult = [[FVPCreationOptions alloc] init]; pigeonResult.asset = asset; pigeonResult.uri = uri; pigeonResult.packageName = packageName; pigeonResult.formatHint = formatHint; pigeonResult.httpHeaders = httpHeaders; + pigeonResult.viewType = viewType; return pigeonResult; } + (FVPCreationOptions *)fromList:(NSArray *)list { @@ -57,6 +70,7 @@ + (FVPCreationOptions *)fromList:(NSArray *)list { pigeonResult.packageName = GetNullableObjectAtIndex(list, 2); pigeonResult.formatHint = GetNullableObjectAtIndex(list, 3); pigeonResult.httpHeaders = GetNullableObjectAtIndex(list, 4); + pigeonResult.viewType = GetNullableObjectAtIndex(list, 5); return pigeonResult; } + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list { @@ -69,6 +83,7 @@ + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list { self.packageName ?: [NSNull null], self.formatHint ?: [NSNull null], self.httpHeaders ?: [NSNull null], + self.viewType ?: [NSNull null], ]; } @end @@ -78,7 +93,11 @@ @interface FVPMessagesPigeonCodecReader : FlutterStandardReader @implementation FVPMessagesPigeonCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { - case 129: + case 129: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil ? nil : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 130: return [FVPCreationOptions fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -90,8 +109,12 @@ @interface FVPMessagesPigeonCodecWriter : FlutterStandardWriter @end @implementation FVPMessagesPigeonCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[FVPCreationOptions class]]) { + if ([value isKindOfClass:[FVPPlatformVideoViewTypeBox class]]) { + FVPPlatformVideoViewTypeBox *box = (FVPPlatformVideoViewTypeBox *)value; [self writeByte:129]; + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[FVPCreationOptions class]]) { + [self writeByte:130]; [self writeValue:[value toList]]; } else { [super writeValue:value]; @@ -114,35 +137,25 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ - FVPMessagesPigeonCodecReaderWriter *readerWriter = - [[FVPMessagesPigeonCodecReaderWriter alloc] init]; + FVPMessagesPigeonCodecReaderWriter *readerWriter = [[FVPMessagesPigeonCodecReaderWriter alloc] init]; sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; }); return sSharedObject; } -void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, - NSObject *api) { +void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *api) { SetUpFVPAVFoundationVideoPlayerApiWithSuffix(binaryMessenger, api, @""); } -void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, - NSObject *api, - NSString *messageChannelSuffix) { - messageChannelSuffix = messageChannelSuffix.length > 0 - ? [NSString stringWithFormat:@".%@", messageChannelSuffix] - : @""; +void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *api, NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 ? [NSString stringWithFormat: @".%@", messageChannelSuffix] : @""; { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.initialize", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(initialize:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", - api); + NSCAssert([api respondsToSelector:@selector(initialize:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { FlutterError *error; [api initialize:&error]; @@ -153,18 +166,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.create", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(createWithOptions:error:)", - api); + NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(createWithOptions:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; FVPCreationOptions *arg_creationOptions = GetNullableObjectAtIndex(args, 0); @@ -177,18 +185,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.dispose", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(disposePlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(disposePlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -201,18 +204,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setLooping", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setLooping:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setLooping:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_isLooping = [GetNullableObjectAtIndex(args, 0) boolValue]; @@ -226,18 +224,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setVolume", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setVolume:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setVolume:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_volume = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -251,18 +244,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setPlaybackSpeed", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setPlaybackSpeed:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setPlaybackSpeed:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_speed = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -276,18 +264,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.play", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert( - [api respondsToSelector:@selector(playPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(playPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -300,18 +283,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.getPosition", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(positionForPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(positionForPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -324,45 +302,33 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.seekTo", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(seekTo:forPlayer:completion:)", - api); + NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(seekTo:forPlayer:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_position = [GetNullableObjectAtIndex(args, 0) integerValue]; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; - [api seekTo:arg_position - forPlayer:arg_textureId - completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api seekTo:arg_position forPlayer:arg_textureId completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.pause", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(pausePlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(pausePlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -375,18 +341,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setMixWithOthers", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setMixWithOthers:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setMixWithOthers:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_mixWithOthers = [GetNullableObjectAtIndex(args, 0) boolValue]; diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index b964d5e38f5..5f2f60c8e32 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -31,7 +31,10 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Future create(DataSource dataSource) async { + Future create( + DataSource dataSource, + VideoViewType viewType, + ) async { String? asset; String? packageName; String? uri; @@ -56,6 +59,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { uri: uri, httpHeaders: httpHeaders, formatHint: formatHint, + viewType: _platformVideoViewTypeFromVideoViewType(viewType), ); return _api.create(options); @@ -140,12 +144,23 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Widget buildView(int textureId) { - // FIXME Use platform view or texture view based on a param. - // FIXME Use a separate class for creation. + Future setMixWithOthers(bool mixWithOthers) { + return _api.setMixWithOthers(mixWithOthers); + } + + @override + Widget buildView(int textureId, VideoViewType viewType) { + return switch (viewType) { + VideoViewType.textureView => Texture(textureId: textureId), + VideoViewType.platformView => _buildPlatformView(textureId, viewType), + }; + } + + Widget _buildPlatformView(int viewId, VideoViewType viewType) { + // FIXME Use a separate class for creation params. final Map creationParams = { - 'viewId': textureId, + 'viewId': viewId, }; return IgnorePointer( // IgnorePointer so that GestureDetector can be used above the platform view. @@ -155,13 +170,6 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { creationParamsCodec: const StandardMessageCodec(), ), ); - - return Texture(textureId: textureId); - } - - @override - Future setMixWithOthers(bool mixWithOthers) { - return _api.setMixWithOthers(mixWithOthers); } EventChannel _eventChannelFor(int textureId) { @@ -184,3 +192,12 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { ); } } + +PlatformVideoViewType _platformVideoViewTypeFromVideoViewType( + VideoViewType viewType, +) { + return switch (viewType) { + VideoViewType.textureView => PlatformVideoViewType.textureView, + VideoViewType.platformView => PlatformVideoViewType.platformView, + }; +} diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index ea4a93fdaba..39c988dec63 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -1,7 +1,7 @@ // 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. -// Autogenerated from Pigeon (v22.4.2), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -18,8 +18,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -29,6 +28,12 @@ List wrapResponse( return [error.code, error.message, error.details]; } +/// Pigeon equivalent of VideoViewType. +enum PlatformVideoViewType { + textureView, + platformView, +} + class CreationOptions { CreationOptions({ this.asset, @@ -36,6 +41,7 @@ class CreationOptions { this.packageName, this.formatHint, required this.httpHeaders, + this.viewType, }); String? asset; @@ -48,6 +54,8 @@ class CreationOptions { Map httpHeaders; + PlatformVideoViewType? viewType; + Object encode() { return [ asset, @@ -55,6 +63,7 @@ class CreationOptions { packageName, formatHint, httpHeaders, + viewType, ]; } @@ -65,12 +74,13 @@ class CreationOptions { uri: result[1] as String?, packageName: result[2] as String?, formatHint: result[3] as String?, - httpHeaders: - (result[4] as Map?)!.cast(), + httpHeaders: (result[4] as Map?)!.cast(), + viewType: result[5] as PlatformVideoViewType?, ); } } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -78,8 +88,11 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is CreationOptions) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); + writeValue(buffer, value.index); + } else if (value is CreationOptions) { + buffer.putUint8(130); writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); @@ -89,7 +102,10 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: + final int? value = readValue(buffer) as int?; + return value == null ? null : PlatformVideoViewType.values[value]; + case 130: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -101,11 +117,9 @@ class AVFoundationVideoPlayerApi { /// Constructor for [AVFoundationVideoPlayerApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - AVFoundationVideoPlayerApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + AVFoundationVideoPlayerApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -113,10 +127,8 @@ class AVFoundationVideoPlayerApi { final String pigeonVar_messageChannelSuffix; Future initialize() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -137,16 +149,14 @@ class AVFoundationVideoPlayerApi { } Future create(CreationOptions creationOptions) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([creationOptions]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([creationOptions]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -166,10 +176,8 @@ class AVFoundationVideoPlayerApi { } Future dispose(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -190,16 +198,14 @@ class AVFoundationVideoPlayerApi { } Future setLooping(bool isLooping, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([isLooping, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([isLooping, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -214,16 +220,14 @@ class AVFoundationVideoPlayerApi { } Future setVolume(double volume, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([volume, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([volume, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -238,16 +242,14 @@ class AVFoundationVideoPlayerApi { } Future setPlaybackSpeed(double speed, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([speed, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([speed, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -262,10 +264,8 @@ class AVFoundationVideoPlayerApi { } Future play(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -286,10 +286,8 @@ class AVFoundationVideoPlayerApi { } Future getPosition(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -315,16 +313,14 @@ class AVFoundationVideoPlayerApi { } Future seekTo(int position, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([position, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([position, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -339,10 +335,8 @@ class AVFoundationVideoPlayerApi { } Future pause(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -363,16 +357,14 @@ class AVFoundationVideoPlayerApi { } Future setMixWithOthers(bool mixWithOthers) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([mixWithOthers]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([mixWithOthers]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { diff --git a/packages/video_player/video_player_avfoundation/pigeons/messages.dart b/packages/video_player/video_player_avfoundation/pigeons/messages.dart index 7a2d2957be1..91190861f52 100644 --- a/packages/video_player/video_player_avfoundation/pigeons/messages.dart +++ b/packages/video_player/video_player_avfoundation/pigeons/messages.dart @@ -17,6 +17,13 @@ import 'package:pigeon/pigeon.dart'; ), copyrightHeader: 'pigeons/copyright.txt', )) + +/// Pigeon equivalent of VideoViewType. +enum PlatformVideoViewType { + textureView, + platformView, +} + class CreationOptions { CreationOptions({required this.httpHeaders}); String? asset; @@ -24,6 +31,7 @@ class CreationOptions { String? packageName; String? formatHint; Map httpHeaders; + PlatformVideoViewType? viewType; } @HostApi(dartHostTestHandler: 'TestHostVideoPlayerApi') diff --git a/packages/video_player/video_player_avfoundation/test/test_api.g.dart b/packages/video_player/video_player_avfoundation/test/test_api.g.dart index 6dbbb53d233..b888c96aa98 100644 --- a/packages/video_player/video_player_avfoundation/test/test_api.g.dart +++ b/packages/video_player/video_player_avfoundation/test/test_api.g.dart @@ -1,7 +1,7 @@ // 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. -// Autogenerated from Pigeon (v22.4.2), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers // ignore_for_file: avoid_relative_lib_imports @@ -13,6 +13,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:video_player_avfoundation/src/messages.g.dart'; + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -20,8 +21,11 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is CreationOptions) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); + writeValue(buffer, value.index); + } else if (value is CreationOptions) { + buffer.putUint8(130); writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); @@ -31,7 +35,10 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: + final int? value = readValue(buffer) as int?; + return value == null ? null : PlatformVideoViewType.values[value]; + case 130: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -40,8 +47,7 @@ class _PigeonCodec extends StandardMessageCodec { } abstract class TestHostVideoPlayerApi { - static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => - TestDefaultBinaryMessengerBinding.instance; + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); void initialize(); @@ -66,58 +72,39 @@ abstract class TestHostVideoPlayerApi { void setMixWithOthers(bool mixWithOthers); - static void setUp( - TestHostVideoPlayerApi? api, { - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) { - messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp(TestHostVideoPlayerApi? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { try { api.initialize(); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null.'); final List args = (message as List?)!; - final CreationOptions? arg_creationOptions = - (args[0] as CreationOptions?); + final CreationOptions? arg_creationOptions = (args[0] as CreationOptions?); assert(arg_creationOptions != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null, expected non-null CreationOptions.'); try { @@ -125,29 +112,22 @@ abstract class TestHostVideoPlayerApi { return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -157,29 +137,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null.'); final List args = (message as List?)!; final bool? arg_isLooping = (args[0] as bool?); assert(arg_isLooping != null, @@ -192,29 +165,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null.'); final List args = (message as List?)!; final double? arg_volume = (args[0] as double?); assert(arg_volume != null, @@ -227,29 +193,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null.'); final List args = (message as List?)!; final double? arg_speed = (args[0] as double?); assert(arg_speed != null, @@ -262,29 +221,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -294,29 +246,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -326,29 +271,22 @@ abstract class TestHostVideoPlayerApi { return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null.'); final List args = (message as List?)!; final int? arg_position = (args[0] as int?); assert(arg_position != null, @@ -361,29 +299,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -393,29 +324,22 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers was null.'); final List args = (message as List?)!; final bool? arg_mixWithOthers = (args[0] as bool?); assert(arg_mixWithOthers != null, @@ -425,9 +349,8 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index d169c5f16d4..dbd8921b5f9 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -49,7 +49,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { } /// Creates an instance of a video player and returns its textureId. - Future create(DataSource dataSource) { + Future create(DataSource dataSource, VideoViewType viewType) { throw UnimplementedError('create() has not been implemented.'); } @@ -94,7 +94,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { } /// Returns a widget displaying the video with a given textureID. - Widget buildView(int textureId) { + Widget buildView(int textureId, VideoViewType viewType) { throw UnimplementedError('buildView() has not been implemented.'); } @@ -111,6 +111,12 @@ abstract class VideoPlayerPlatform extends PlatformInterface { class _PlaceholderImplementation extends VideoPlayerPlatform {} +// FIXME Add docs +enum VideoViewType { + textureView, + platformView, +} + /// Description of the data source used to create an instance of /// the video player. class DataSource { From dc857565a7ee58350646fceedba0718518540a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 18 Nov 2024 16:58:49 +0100 Subject: [PATCH 023/167] Pass video view type to controller in iOS example project --- .../video_player_avfoundation/example/lib/main.dart | 8 +++++++- .../example/lib/mini_controller.dart | 13 ++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index 313ae7f50dc..a0b73ce3ede 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -5,6 +5,7 @@ // ignore_for_file: public_member_api_docs import 'package:flutter/material.dart'; +import 'package:video_player_platform_interface/video_player_platform_interface.dart'; import 'mini_controller.dart'; @@ -63,7 +64,10 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { @override void initState() { super.initState(); - _controller = MiniController.asset('assets/Butterfly-209.mp4'); + _controller = MiniController.asset( + 'assets/Butterfly-209.mp4', + viewType: VideoViewType.platformView, + ); _controller.addListener(() { setState(() {}); @@ -120,6 +124,7 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { super.initState(); _controller = MiniController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', + viewType: VideoViewType.platformView, ); _controller.addListener(() { @@ -176,6 +181,7 @@ class _BumbleBeeEncryptedLiveStreamState super.initState(); _controller = MiniController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/encrypted_bee.m3u8', + viewType: VideoViewType.textureView, ); _controller.addListener(() { diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index a38013533d6..bf08307e1d8 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -167,19 +167,19 @@ class MiniController extends ValueNotifier { /// The name of the asset is given by the [dataSource] argument and must not be /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. - MiniController.asset(this.dataSource, {this.package}) + MiniController.asset(this.dataSource, {this.package, required this.viewType}) : dataSourceType = DataSourceType.asset, super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [MiniController] playing a video from obtained from /// the network. - MiniController.network(this.dataSource) + MiniController.network(this.dataSource, {required this.viewType}) : dataSourceType = DataSourceType.network, package = null, super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [MiniController] playing a video from obtained from a file. - MiniController.file(File file) + MiniController.file(File file, {required this.viewType}) : dataSource = Uri.file(file.absolute.path).toString(), dataSourceType = DataSourceType.file, package = null, @@ -196,6 +196,9 @@ class MiniController extends ValueNotifier { /// Only set for [asset] videos. The package that the asset was loaded from. final String? package; + // FIXME Document + final VideoViewType viewType; + Timer? _timer; Completer? _creatingCompleter; StreamSubscription? _eventSubscription; @@ -239,7 +242,7 @@ class MiniController extends ValueNotifier { ); } - _textureId = (await _platform.create(dataSourceDescription)) ?? + _textureId = (await _platform.create(dataSourceDescription, viewType)) ?? kUninitializedTextureId; _creatingCompleter!.complete(null); final Completer initializingCompleter = Completer(); @@ -422,7 +425,7 @@ class _VideoPlayerState extends State { Widget build(BuildContext context) { return _textureId == MiniController.kUninitializedTextureId ? Container() - : _platform.buildView(_textureId); + : _platform.buildView(_textureId, widget.controller.viewType); } } From c9f27c5e70382471be12b03fd93cde9d12adf09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 18 Nov 2024 19:17:35 +0100 Subject: [PATCH 024/167] Add two FVPVideoPlayer implementations - basic and texture-approach oriented --- .../FVPVideoPlayerPlugin.m | 71 +++++++++++++------ 1 file changed, 49 insertions(+), 22 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 8a32dc7717d..39639a3f201 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 @@ -77,8 +77,14 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { - int64_t textureId = [self.registry registerTexture:player]; - frameUpdater.textureId = textureId; + int64_t textureId; + if (frameUpdater != nil) { + textureId = [self.registry registerTexture:player]; + frameUpdater.textureId = textureId; + } else { + textureId = arc4random(); + } + FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:[NSString stringWithFormat:@"flutter.io/videoPlayer/videoEvents%lld", textureId] @@ -87,9 +93,13 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater player.eventChannel = eventChannel; self.playersByTextureId[@(textureId)] = player; - // Ensure that the first frame is drawn once available, even if the video isn't played, since - // the engine is now expecting the texture to be populated. - [player expectFrame]; + // FIXME Does it need to be here? + if (frameUpdater != nil) { + // Ensure that the first frame is drawn once available, even if the video isn't played, since + // the engine is now expecting the texture to be populated. + // We can safely cast to FVPVideoPlayerTextureApproach since frameUpdater is non-nil. + [(FVPVideoPlayerTextureApproach *)player expectFrame]; + } return textureId; } @@ -110,12 +120,15 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options error:(FlutterError **)error { - FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; - FVPDisplayLink *displayLink = - [self.displayLinkFactory displayLinkWithRegistrar:_registrar - callback:^() { - [frameUpdater displayLinkFired]; - }]; + FVPFrameUpdater *frameUpdater; + FVPDisplayLink *displayLink; + if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; + displayLink = [self.displayLinkFactory displayLinkWithRegistrar:_registrar + callback:^() { + [frameUpdater displayLinkFired]; + }]; + } FVPVideoPlayer *player; if (options.asset) { @@ -126,23 +139,36 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options assetPath = [_registrar lookupKeyForAsset:options.asset]; } @try { - player = [[FVPVideoPlayer alloc] initWithAsset:assetPath - frameUpdater:frameUpdater - displayLink:displayLink - avFactory:_avFactory - registrar:self.registrar]; + if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + player = [[FVPVideoPlayerTextureApproach alloc] initWithAsset:assetPath + frameUpdater:frameUpdater + displayLink:displayLink + avFactory:_avFactory + registrar:self.registrar]; + } else { + player = [[FVPVideoPlayer alloc] initWithAsset:assetPath + avFactory:_avFactory + registrar:self.registrar]; + } return @([self onPlayerSetup:player frameUpdater:frameUpdater]); } @catch (NSException *exception) { *error = [FlutterError errorWithCode:@"video_player" message:exception.reason details:nil]; return nil; } } else if (options.uri) { - player = [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] - frameUpdater:frameUpdater - displayLink:displayLink - httpHeaders:options.httpHeaders - avFactory:_avFactory - registrar:self.registrar]; + if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + player = [[FVPVideoPlayerTextureApproach alloc] initWithURL:[NSURL URLWithString:options.uri] + frameUpdater:frameUpdater + displayLink:displayLink + httpHeaders:options.httpHeaders + avFactory:_avFactory + registrar:self.registrar]; + } else { + player = [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] + httpHeaders:options.httpHeaders + avFactory:_avFactory + registrar:self.registrar]; + } return @([self onPlayerSetup:player frameUpdater:frameUpdater]); } else { *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; @@ -153,6 +179,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options - (void)disposePlayer:(NSInteger)textureId error:(FlutterError **)error { NSNumber *playerKey = @(textureId); FVPVideoPlayer *player = self.playersByTextureId[playerKey]; + // FIXME Only unregister texture when using texture approach [self.registry unregisterTexture:textureId]; [self.playersByTextureId removeObjectForKey:playerKey]; if (!player.disposed) { From b3151e28e2cc703b6a73ba5cdda2db3eba1ec4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 10:49:31 +0100 Subject: [PATCH 025/167] Split iOS native classes into multiple files --- .../FVPNativeVideoView.m | 43 +++++ .../FVPNativeVideoViewFactory.m | 35 ++++ .../FVPVideoPlayer.m | 135 ++------------ .../FVPVideoPlayerPlugin.m | 3 + .../FVPVideoPlayerTextureApproach.m | 164 ++++++++++++++++++ .../FVPNativeVideoView.h | 11 ++ .../FVPNativeVideoViewFactory.h | 13 ++ .../FVPVideoPlayerPlugin.h | 14 -- .../FVPVideoPlayerTextureApproach.h | 33 ++++ 9 files changed, 313 insertions(+), 138 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m new file mode 100644 index 00000000000..07b269842af --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m @@ -0,0 +1,43 @@ +#import + +#import "FVPNativeVideoView.h" + +@interface FVPPlayerView : UIView +@end + +@implementation FVPPlayerView ++ (Class)layerClass { + return [AVPlayerLayer class]; +} + +- (void)setPlayer:(AVPlayer *)player { + [(AVPlayerLayer *)[self layer] setPlayer:player]; +} +@end + +@implementation FVPNativeVideoView { + FVPPlayerView *_view; +} + +- (instancetype)initWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args + binaryMessenger:(NSObject *)messenger + player:(AVPlayer *)player { + if (self = [super init]) { + _view = [[FVPPlayerView alloc] init]; + [_view setPlayer:player]; + } + return self; +} + +- (FVPPlayerView *)view { + return _view; +} + +- (void)dealloc { + [_view setPlayer:nil]; + _view = nil; +} + +@end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m new file mode 100644 index 00000000000..e90f1e2117b --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m @@ -0,0 +1,35 @@ +#import "FVPNativeVideoViewFactory.h" +#import "FVPNativeVideoView.h" +#import "FVPVideoPlayer.h" + +@implementation FVPNativeVideoViewFactory { + NSObject *_messenger; + NSMutableDictionary *_playersByTextureId; +} +- (instancetype)initWithMessenger:(NSObject *)messenger + playersByTextureId: + (NSMutableDictionary *)playersByTextureId { + self = [super init]; + if (self) { + _messenger = messenger; + _playersByTextureId = playersByTextureId; + } + return self; +} + +- (NSObject *)createWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args { + NSNumber *viewIdFromArgs = args[@"viewId"]; + FVPVideoPlayer *player = _playersByTextureId[viewIdFromArgs]; + return [[FVPNativeVideoView alloc] initWithFrame:frame + viewIdentifier:viewId + arguments:args + binaryMessenger:_messenger + player:player.player]; +} + +- (NSObject *)createArgsCodec { + return [FlutterStandardMessageCodec sharedInstance]; +} +@end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 31db6221d94..97e496ad66f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -44,8 +44,6 @@ - (void)updatePlayingState; @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar { NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; @@ -57,8 +55,6 @@ - (instancetype)initWithAsset:(NSString *)asset } #endif return [self initWithURL:[NSURL fileURLWithPath:path] - frameUpdater:frameUpdater - displayLink:displayLink httpHeaders:@{} avFactory:avFactory registrar:registrar]; @@ -172,8 +168,6 @@ - (AVMutableVideoComposition *)getVideoCompositionWithTransform:(CGAffineTransfo } - (instancetype)initWithURL:(NSURL *)url - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory registrar:(NSObject *)registrar { @@ -183,23 +177,16 @@ - (instancetype)initWithURL:(NSURL *)url } AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:options]; AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:urlAsset]; - return [self initWithPlayerItem:item - frameUpdater:frameUpdater - displayLink:(FVPDisplayLink *)displayLink - avFactory:avFactory - registrar:registrar]; + return [self initWithPlayerItem:item avFactory:avFactory registrar:registrar]; } - (instancetype)initWithPlayerItem:(AVPlayerItem *)item - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar { self = [super init]; NSAssert(self, @"super init cannot be nil"); _registrar = registrar; - _frameUpdater = frameUpdater; AVAsset *asset = [item asset]; void (^assetCompletionHandler)(void) = ^{ @@ -233,22 +220,12 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item _player = [avFactory playerWithPlayerItem:item]; _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; - // 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]; - [self.flutterViewLayer addSublayer:_playerLayer]; - // Configure output. - _displayLink = displayLink; NSDictionary *pixBuffAttributes = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA), (id)kCVPixelBufferIOSurfacePropertiesKey : @{} }; _videoOutput = [avFactory videoOutputWithPixelBufferAttributes:pixBuffAttributes]; - frameUpdater.videoOutput = _videoOutput; [self addObserversForItem:item player:_player]; @@ -275,7 +252,13 @@ - (void)observeValueForKeyPath:(NSString *)path AVPlayerItem *item = (AVPlayerItem *)object; switch (item.status) { case AVPlayerItemStatusFailed: - [self sendFailedToLoadVideoEvent]; + if (_eventSink != nil) { + _eventSink([FlutterError + errorWithCode:@"VideoError" + message:[@"Failed to load video: " + stringByAppendingString:[item.error localizedDescription]] + details:nil]); + } break; case AVPlayerItemStatusUnknown: break; @@ -325,35 +308,6 @@ - (void)updatePlayingState { } else { [_player pause]; } - // If the texture is still waiting for an expected frame, the display link needs to keep - // running until it arrives regardless of the play/pause state. - _displayLink.running = _isPlaying || self.waitingForFrame; -} - -- (void)sendFailedToLoadVideoEvent { - if (_eventSink == nil) { - return; - } - // 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) { - [details addObject:detail]; - } - }; - NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; - add(error.localizedDescription); - add(error.localizedFailureReason); - add(underlyingError.localizedDescription); - add(underlyingError.localizedFailureReason); - NSString *message = [details.array componentsJoinedByString:@": "]; - _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); } - (void)setupEventSinkIfReadyToPlay { @@ -439,27 +393,12 @@ - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHan toleranceBefore:tolerance toleranceAfter:tolerance completionHandler:^(BOOL completed) { - if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { - // Ensure that a frame is drawn once available, even if currently paused. In theory a race - // is possible here where the new frame has already drawn by the time this code runs, and - // the display link stays on indefinitely, but that should be relatively harmless. This - // must use the display link rather than just informing the engine that a new frame is - // available because the seek completing doesn't guarantee that the pixel buffer is - // already available. - [self expectFrame]; - } - if (completionHandler) { completionHandler(completed); } }]; } -- (void)expectFrame { - self.waitingForFrame = YES; - self.displayLink.running = YES; -} - - (void)setIsLooping:(BOOL)isLooping { _isLooping = isLooping; } @@ -492,38 +431,6 @@ - (void)setPlaybackSpeed:(double)speed { _player.rate = speed; } -- (CVPixelBufferRef)copyPixelBuffer { - CVPixelBufferRef buffer = NULL; - CMTime outputItemTime = [_videoOutput itemTimeForHostTime:CACurrentMediaTime()]; - if ([_videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { - buffer = [_videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; - } else { - // If the current time isn't available yet, use the time that was checked when informing the - // engine that a frame was available (if any). - CMTime lastAvailableTime = self.frameUpdater.lastKnownAvailableTime; - if (CMTIME_IS_VALID(lastAvailableTime)) { - buffer = [_videoOutput copyPixelBufferForItemTime:lastAvailableTime itemTimeForDisplay:NULL]; - } - } - - if (self.waitingForFrame && buffer) { - self.waitingForFrame = NO; - // If the display link was only running temporarily to pick up a new frame while the video was - // paused, stop it again. - if (!self.isPlaying) { - self.displayLink.running = NO; - } - } - - return buffer; -} - -- (void)onTextureUnregistered:(NSObject *)texture { - dispatch_async(dispatch_get_main_queue(), ^{ - [self dispose]; - }); -} - - (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { _eventSink = nil; return nil; @@ -537,17 +444,13 @@ - (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) - // 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]; - return nil; - } [self setupEventSinkIfReadyToPlay]; return nil; } +/// This method allows you to dispose without touching the event channel. This +/// is useful for the case where the Engine is in the process of deconstruction +/// so the channel is going to die or is already dead. - (void)disposeSansEventChannel { // This check prevents the crash caused by removing the KVO observers twice. // When performing a Hot Restart, the leftover players are disposed once directly @@ -558,8 +461,6 @@ - (void)disposeSansEventChannel { } _disposed = YES; - [_playerLayer removeFromSuperlayer]; - _displayLink = nil; [self removeKeyValueObservers]; [self.player replaceCurrentItemWithPlayerItem:nil]; @@ -571,20 +472,6 @@ - (void)dispose { [_eventChannel setStreamHandler:nil]; } -- (CALayer *)flutterViewLayer { -#if TARGET_OS_OSX - return self.registrar.view.layer; -#else -#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 - UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; -#pragma clang diagnostic pop - return root.view.layer; -#endif -} - /// Removes all key-value observers set up for the player. /// /// This is called from dealloc, so must not use any methods on self. 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 39639a3f201..bc0b9f33af3 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 @@ -9,7 +9,10 @@ #import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" +#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" +#import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" #import "./include/video_player_avfoundation/messages.g.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m new file mode 100644 index 00000000000..fbf77d32315 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m @@ -0,0 +1,164 @@ +#import "FVPVideoPlayerTextureApproach.h" + +@implementation FVPVideoPlayerTextureApproach +- (instancetype)initWithAsset:(NSString *)asset + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; +#if TARGET_OS_OSX + // See https://github.com/flutter/flutter/issues/135302 + // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. + if (!path) { + path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; + } +#endif + return [self initWithURL:[NSURL fileURLWithPath:path] + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:@{} + avFactory:avFactory + registrar:registrar]; +} + +- (instancetype)initWithURL:(NSURL *)url + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:(nonnull NSDictionary *)headers + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + NSDictionary *options = nil; + if ([headers count] != 0) { + options = @{@"AVURLAssetHTTPHeaderFieldsKey" : headers}; + } + AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:options]; + AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:urlAsset]; + return [self initWithPlayerItem:item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:avFactory + registrar:registrar]; +} + +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar { + self = [super initWithPlayerItem:item avFactory:avFactory registrar:registrar]; + + if (self) { + _frameUpdater = frameUpdater; + _displayLink = displayLink; + _frameUpdater.videoOutput = self.videoOutput; + + // 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. + self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; + [self.flutterViewLayer addSublayer:self.playerLayer]; + } + return self; +} + +- (void)updatePlayingState { + [super updatePlayingState]; + // If the texture is still waiting for an expected frame, the display link needs to keep + // running until it arrives regardless of the play/pause state. + _displayLink.running = self.isPlaying || self.waitingForFrame; +} + +- (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { + // FIXME Rethink if it's possible to reuse it (same logic in super class) + CMTime previousCMTime = self.player.currentTime; + CMTime targetCMTime = CMTimeMake(location, 1000); + CMTimeValue duration = self.player.currentItem.asset.duration.value; + // Without adding tolerance when seeking to duration, + // seekToTime will never complete, and this call will hang. + // see issue https://github.com/flutter/flutter/issues/124475. + CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero; + [self.player seekToTime:targetCMTime + toleranceBefore:tolerance + toleranceAfter:tolerance + completionHandler:^(BOOL completed) { + if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { + // Ensure that a frame is drawn once available, even if currently paused. In theory a + // race is possible here where the new frame has already drawn by the time this code + // runs, and the display link stays on indefinitely, but that should be relatively + // harmless. This must use the display link rather than just informing the engine that a + // new frame is available because the seek completing doesn't guarantee that the pixel + // buffer is already available. + [self expectFrame]; + } + + if (completionHandler) { + completionHandler(completed); + } + }]; +} + +- (void)expectFrame { + self.waitingForFrame = YES; + + self.displayLink.running = YES; +} + +- (CVPixelBufferRef)copyPixelBuffer { + CVPixelBufferRef buffer = NULL; + CMTime outputItemTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; + if ([self.videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { + buffer = [self.videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; + } else { + // If the current time isn't available yet, use the time that was checked when informing the + // engine that a frame was available (if any). + CMTime lastAvailableTime = self.frameUpdater.lastKnownAvailableTime; + if (CMTIME_IS_VALID(lastAvailableTime)) { + buffer = [self.videoOutput copyPixelBufferForItemTime:lastAvailableTime + itemTimeForDisplay:NULL]; + } + } + + if (self.waitingForFrame && buffer) { + self.waitingForFrame = NO; + // If the display link was only running temporarily to pick up a new frame while the video was + // paused, stop it again. + if (!self.isPlaying) { + self.displayLink.running = NO; + } + } + + return buffer; +} + +- (void)onTextureUnregistered:(NSObject *)texture { + dispatch_async(dispatch_get_main_queue(), ^{ + [self dispose]; + }); +} + +- (void)disposeSansEventChannel { + [super disposeSansEventChannel]; + + [self.playerLayer removeFromSuperlayer]; + + _displayLink = nil; +} + +- (CALayer *)flutterViewLayer { +#if TARGET_OS_OSX + return self.registrar.view.layer; +#else +#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 + UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; +#pragma clang diagnostic pop + return root.view.layer; +#endif +} + +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h new file mode 100644 index 00000000000..299aa17c113 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -0,0 +1,11 @@ +#import + +@interface FVPNativeVideoView : NSObject +- (instancetype)initWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args + binaryMessenger:(NSObject *)messenger + player:(AVPlayer *)player; + +- (UIView *)view; +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h new file mode 100644 index 00000000000..a119258efc7 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -0,0 +1,13 @@ +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import "FVPVideoPlayer.h" + +@interface FVPNativeVideoViewFactory : NSObject +- (instancetype)initWithMessenger:(NSObject *)messenger + playersByTextureId: + (NSMutableDictionary *)playersByTextureId; +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h index 9e2f3028939..9a2d168337d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h @@ -13,17 +13,3 @@ @interface FVPVideoPlayerPlugin : NSObject - (instancetype)initWithRegistrar:(NSObject *)registrar; @end - -@interface FVPNativeVideoViewFactory : NSObject -- (instancetype)initWithMessenger:(NSObject *)messenger; -@end - -@interface FVPNativeVideoView : NSObject -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - binaryMessenger:(NSObject *)messenger - player:(AVPlayer *)player; - -- (UIView *)view; -@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h new file mode 100644 index 00000000000..1b29cb3ece5 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -0,0 +1,33 @@ +#import "FVPDisplayLink.h" +#import "FVPFrameUpdater.h" +#import "FVPVideoPlayer.h" + +@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer +// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly) CALayer *flutterViewLayer; +// The updater that drives callbacks to the engine to indicate that a new frame is ready. +@property(nonatomic) FVPFrameUpdater *frameUpdater; +// The display link that drives frameUpdater. +@property(nonatomic) FVPDisplayLink *displayLink; +// Whether a new frame needs to be provided to the engine regardless of the current play/pause state +// (e.g., after a seek while paused). If YES, the display link should continue to run until the next +// frame is successfully provided. +@property(nonatomic, assign) BOOL waitingForFrame; + +- (instancetype)initWithURL:(NSURL *)url + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + httpHeaders:(nonnull NSDictionary *)headers + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +- (instancetype)initWithAsset:(AVPlayerItem *)item + frameUpdater:(FVPFrameUpdater *)frameUpdater + displayLink:(FVPDisplayLink *)displayLink + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +// Tells the player to run its frame updater until it receives a frame, regardless of the +// play/pause state. +- (void)expectFrame; +@end From db1a9439c742d35965752559919a50f2fe71dc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 12:16:31 +0100 Subject: [PATCH 026/167] Only register native view factory for iOS, not MacOS --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 7 ++++++- .../video_player_avfoundation/FVPNativeVideoView.h | 12 ++++++++++++ .../FVPNativeVideoView.m | 2 +- .../FVPNativeVideoViewFactory.m | 0 4 files changed, 19 insertions(+), 2 deletions(-) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation => video_player_avfoundation_ios}/FVPNativeVideoView.m (89%) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation => video_player_avfoundation_ios}/FVPNativeVideoViewFactory.m (100%) 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 bc0b9f33af3..b13827482f0 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 @@ -9,13 +9,16 @@ #import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" -#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" #import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" #import "./include/video_player_avfoundation/messages.g.h" +#if TARGET_OS_IOS +#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" +#endif + #if !__has_feature(objc_arc) #error Code Requires ARC. #endif @@ -46,10 +49,12 @@ @implementation FVPVideoPlayerPlugin + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; +#if TARGET_OS_IOS FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger playersByTextureId:instance.playersByTextureId]; [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; +#endif SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index 299aa17c113..1ed6f019edf 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -1,11 +1,23 @@ +#if TARGET_OS_OSX +#import +#else #import +#endif +#if TARGET_OS_OSX +@interface FVPNativeVideoView : NSView +#else @interface FVPNativeVideoView : NSObject +#endif - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args binaryMessenger:(NSObject *)messenger player:(AVPlayer *)player; +#if TARGET_OS_OSX +- (NSView *)view; +#else - (UIView *)view; +#endif @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m similarity index 89% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 07b269842af..bb208d7cc21 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -1,6 +1,6 @@ #import -#import "FVPNativeVideoView.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" @interface FVPPlayerView : UIView @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m similarity index 100% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m From 0e3b346a4c0fdb82512dd04bed53fefb51151ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 12:17:26 +0100 Subject: [PATCH 027/167] Use only textue view on MacOS in example app --- .../video_player_avfoundation/example/lib/main.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index a0b73ce3ede..72b36df8ed2 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -4,6 +4,8 @@ // ignore_for_file: public_member_api_docs +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -66,7 +68,9 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { super.initState(); _controller = MiniController.asset( 'assets/Butterfly-209.mp4', - viewType: VideoViewType.platformView, + viewType: Platform.isIOS + ? VideoViewType.platformView + : VideoViewType.textureView, ); _controller.addListener(() { @@ -124,7 +128,9 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { super.initState(); _controller = MiniController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', - viewType: VideoViewType.platformView, + viewType: Platform.isIOS + ? VideoViewType.platformView + : VideoViewType.textureView, ); _controller.addListener(() { From 6d317a5fd2fb437f88b064dcb8e4fd9ce2cd8e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 12:33:54 +0100 Subject: [PATCH 028/167] Refactor imports --- .../FVPVideoPlayerPlugin.m | 2 + .../video_player_avfoundation/messages.g.m | 210 ++++++++++++------ .../FVPDisplayLink.m | 4 +- .../FVPNativeVideoView.m | 2 +- 4 files changed, 143 insertions(+), 75 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 b13827482f0..a1b57b0b233 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 @@ -13,6 +13,8 @@ #import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" #import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" +// Relative path is needed for messages.g.h. See: +// https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 #import "./include/video_player_avfoundation/messages.g.h" #if TARGET_OS_IOS diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index c26cfb0227f..255fbd8bbba 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -4,14 +4,16 @@ // Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import "./include/video_player_avfoundation/messages.g.h" - #if TARGET_OS_OSX #import #else #import #endif +// Relative path is needed for messages.g.h. See: +// https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 +#import "./include/video_player_avfoundation/messages.g.h" + #if !__has_feature(objc_arc) #error File requires ARC to be enabled. #endif @@ -49,12 +51,12 @@ + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list; @implementation FVPCreationOptions + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { - FVPCreationOptions* pigeonResult = [[FVPCreationOptions alloc] init]; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { + FVPCreationOptions *pigeonResult = [[FVPCreationOptions alloc] init]; pigeonResult.asset = asset; pigeonResult.uri = uri; pigeonResult.packageName = packageName; @@ -95,9 +97,11 @@ - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 129: { NSNumber *enumAsNumber = [self readValue]; - return enumAsNumber == nil ? nil : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + return enumAsNumber == nil + ? nil + : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; } - case 130: + case 130: return [FVPCreationOptions fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -137,25 +141,35 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ - FVPMessagesPigeonCodecReaderWriter *readerWriter = [[FVPMessagesPigeonCodecReaderWriter alloc] init]; + FVPMessagesPigeonCodecReaderWriter *readerWriter = + [[FVPMessagesPigeonCodecReaderWriter alloc] init]; sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; }); return sSharedObject; } -void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *api) { +void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, + NSObject *api) { SetUpFVPAVFoundationVideoPlayerApiWithSuffix(binaryMessenger, api, @""); } -void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *api, NSString *messageChannelSuffix) { - messageChannelSuffix = messageChannelSuffix.length > 0 ? [NSString stringWithFormat: @".%@", messageChannelSuffix] : @""; +void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, + NSObject *api, + NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 + ? [NSString stringWithFormat:@".%@", messageChannelSuffix] + : @""; { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.initialize", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(initialize:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", api); + NSCAssert([api respondsToSelector:@selector(initialize:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { FlutterError *error; [api initialize:&error]; @@ -166,13 +180,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.create", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(createWithOptions:error:)", api); + NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(createWithOptions:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; FVPCreationOptions *arg_creationOptions = GetNullableObjectAtIndex(args, 0); @@ -185,13 +204,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.dispose", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(disposePlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(disposePlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -204,13 +228,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setLooping", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setLooping:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setLooping:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_isLooping = [GetNullableObjectAtIndex(args, 0) boolValue]; @@ -224,13 +253,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setVolume", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setVolume:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setVolume:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_volume = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -244,13 +278,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setPlaybackSpeed", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setPlaybackSpeed:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setPlaybackSpeed:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_speed = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -264,13 +303,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.play", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(playPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", api); + NSCAssert( + [api respondsToSelector:@selector(playPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -283,13 +327,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.getPosition", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(positionForPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(positionForPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -302,33 +351,45 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.seekTo", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(seekTo:forPlayer:completion:)", api); + NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(seekTo:forPlayer:completion:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_position = [GetNullableObjectAtIndex(args, 0) integerValue]; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; - [api seekTo:arg_position forPlayer:arg_textureId completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api seekTo:arg_position + forPlayer:arg_textureId + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.pause", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(pausePlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(pausePlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -341,13 +402,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setMixWithOthers", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setMixWithOthers:error:)", api); + NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setMixWithOthers:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_mixWithOthers = [GetNullableObjectAtIndex(args, 0) boolValue]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m index 9bdb321ae16..c3921496a35 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "../video_player_avfoundation/include/video_player_avfoundation/FVPDisplayLink.h" - #import #import +#import "FVPDisplayLink.h" + /// A proxy object to act as a CADisplayLink target, to avoid retain loops, since FVPDisplayLink /// owns its CADisplayLink, but CADisplayLink retains its target. @interface FVPDisplayLinkTarget : NSObject diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index bb208d7cc21..07b269842af 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -1,6 +1,6 @@ #import -#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" +#import "FVPNativeVideoView.h" @interface FVPPlayerView : UIView @end From 9bace4061fe91b0b16eac1b42d112843b89cd6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 13:20:07 +0100 Subject: [PATCH 029/167] Allow choosing between texture view and platform view in example app --- .../example/lib/main.dart | 98 ++++++++++++++++--- 1 file changed, 86 insertions(+), 12 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index 72b36df8ed2..e043e05b882 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -4,8 +4,6 @@ // ignore_for_file: public_member_api_docs -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -45,9 +43,18 @@ class _App extends StatelessWidget { ), body: TabBarView( children: [ - _BumbleBeeRemoteVideo(), - _BumbleBeeEncryptedLiveStream(), - _ButterFlyAssetVideo(), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeRemoteVideo(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeEncryptedLiveStream(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _ButterFlyAssetVideo(viewType), + ), ], ), ), @@ -55,7 +62,70 @@ class _App extends StatelessWidget { } } +class _ViewTypeTabBar extends StatefulWidget { + const _ViewTypeTabBar({ + required this.builder, + }); + + final Widget Function(VideoViewType) builder; + + @override + State<_ViewTypeTabBar> createState() => _ViewTypeTabBarState(); +} + +class _ViewTypeTabBarState extends State<_ViewTypeTabBar> + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + TabBar( + controller: _tabController, + isScrollable: true, + tabs: const [ + Tab( + icon: Icon(Icons.texture), + text: 'Texture view', + ), + Tab( + icon: Icon(Icons.construction), + text: 'Platform view', + ), + ], + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + widget.builder(VideoViewType.textureView), + widget.builder(VideoViewType.platformView), + ], + ), + ), + ], + ); + } +} + class _ButterFlyAssetVideo extends StatefulWidget { + const _ButterFlyAssetVideo(this.viewType); + + final VideoViewType viewType; + @override _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState(); } @@ -68,9 +138,7 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { super.initState(); _controller = MiniController.asset( 'assets/Butterfly-209.mp4', - viewType: Platform.isIOS - ? VideoViewType.platformView - : VideoViewType.textureView, + viewType: widget.viewType, ); _controller.addListener(() { @@ -116,6 +184,10 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { } class _BumbleBeeRemoteVideo extends StatefulWidget { + const _BumbleBeeRemoteVideo(this.viewType); + + final VideoViewType viewType; + @override _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState(); } @@ -128,9 +200,7 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { super.initState(); _controller = MiniController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', - viewType: Platform.isIOS - ? VideoViewType.platformView - : VideoViewType.textureView, + viewType: widget.viewType, ); _controller.addListener(() { @@ -173,6 +243,10 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { } class _BumbleBeeEncryptedLiveStream extends StatefulWidget { + const _BumbleBeeEncryptedLiveStream(this.viewType); + + final VideoViewType viewType; + @override _BumbleBeeEncryptedLiveStreamState createState() => _BumbleBeeEncryptedLiveStreamState(); @@ -187,7 +261,7 @@ class _BumbleBeeEncryptedLiveStreamState super.initState(); _controller = MiniController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/encrypted_bee.m3u8', - viewType: VideoViewType.textureView, + viewType: widget.viewType, ); _controller.addListener(() { From 3bf34f9003e34361f071c0f496556f36efc5a961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 13:38:08 +0100 Subject: [PATCH 030/167] Remove redundant import --- .../include/video_player_avfoundation/FVPVideoPlayerPlugin.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h index 9a2d168337d..b64a173fe0c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin.h @@ -8,8 +8,6 @@ #import #endif -#import - @interface FVPVideoPlayerPlugin : NSObject - (instancetype)initWithRegistrar:(NSObject *)registrar; @end From 40996c471fef9de3bb18d043b81222474a209b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 13:38:24 +0100 Subject: [PATCH 031/167] Add some fixme comments for later --- .../include/video_player_avfoundation/FVPNativeVideoView.h | 3 +++ .../video_player_avfoundation/FVPVideoPlayerTextureApproach.h | 1 + .../Sources/video_player_avfoundation_ios/FVPNativeVideoView.m | 1 + 3 files changed, 5 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index 1ed6f019edf..d969355da0d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -4,6 +4,9 @@ #import #endif +// FIXME Do we even need ifs below? MacOS currently doesn't support FlutterPlatformView. +// But can we complie code without it? And is it good to put iOS-specific code in the main +// directory (video_player_avfoundation? #if TARGET_OS_OSX @interface FVPNativeVideoView : NSView #else diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index 1b29cb3ece5..aa6f55b18a9 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -2,6 +2,7 @@ #import "FVPFrameUpdater.h" #import "FVPVideoPlayer.h" +// FIXME Add docs - what functionality this class adds. @interface FVPVideoPlayerTextureApproach : FVPVideoPlayer // The CALayer associated with the Flutter view this plugin is associated with, if any. @property(nonatomic, readonly) CALayer *flutterViewLayer; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 07b269842af..c40331700a3 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -2,6 +2,7 @@ #import "FVPNativeVideoView.h" +// FIXME Add some docs for FVPNativeVideoView and possibly FVPPlayerView @interface FVPPlayerView : UIView @end From 674f9d0fbf3096ca5375509f9b09cf6088bbca62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 13:40:05 +0100 Subject: [PATCH 032/167] Add copyright to each native iOS file --- .../video_player_avfoundation/FVPVideoPlayerTextureApproach.m | 4 ++++ .../include/video_player_avfoundation/FVPNativeVideoView.h | 4 ++++ .../video_player_avfoundation/FVPNativeVideoViewFactory.h | 4 ++++ .../video_player_avfoundation/FVPVideoPlayerTextureApproach.h | 4 ++++ .../video_player_avfoundation_ios/FVPNativeVideoView.m | 4 ++++ .../video_player_avfoundation_ios/FVPNativeVideoViewFactory.m | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m index fbf77d32315..c94cb556edb 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m @@ -1,3 +1,7 @@ +// 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 "FVPVideoPlayerTextureApproach.h" @implementation FVPVideoPlayerTextureApproach diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index d969355da0d..871ac36fcfa 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -1,3 +1,7 @@ +// 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. + #if TARGET_OS_OSX #import #else diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index a119258efc7..64fb7c7a1f8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -1,3 +1,7 @@ +// 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. + #if TARGET_OS_OSX #import #else diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index aa6f55b18a9..bfad965a4a3 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -1,3 +1,7 @@ +// 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 "FVPDisplayLink.h" #import "FVPFrameUpdater.h" #import "FVPVideoPlayer.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index c40331700a3..f8050466ec3 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -1,3 +1,7 @@ +// 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 #import "FVPNativeVideoView.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index e90f1e2117b..741179f2e8e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -1,3 +1,7 @@ +// 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 "FVPNativeVideoViewFactory.h" #import "FVPNativeVideoView.h" #import "FVPVideoPlayer.h" From 3806bd2b9012d870c4d23820b6022953b25a38c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 13:45:06 +0100 Subject: [PATCH 033/167] Rename viewId to playerId in params --- .../FVPNativeVideoViewFactory.m | 2 +- .../lib/src/avfoundation_video_player.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 741179f2e8e..be036f43296 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -24,7 +24,7 @@ - (instancetype)initWithMessenger:(NSObject *)messenger - (NSObject *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { - NSNumber *viewIdFromArgs = args[@"viewId"]; + NSNumber *viewIdFromArgs = args[@"playerId"]; FVPVideoPlayer *player = _playersByTextureId[viewIdFromArgs]; return [[FVPNativeVideoView alloc] initWithFrame:frame viewIdentifier:viewId diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 5f2f60c8e32..f1fd6fb4274 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -25,6 +25,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { return _api.initialize(); } + // FIXME Rename textureId everywhere to playerId. @override Future dispose(int textureId) { return _api.dispose(textureId); @@ -156,11 +157,10 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { }; } - Widget _buildPlatformView(int viewId, VideoViewType viewType) { + Widget _buildPlatformView(int playerId, VideoViewType viewType) { // FIXME Use a separate class for creation params. - final Map creationParams = { - 'viewId': viewId, + 'playerId': playerId, }; return IgnorePointer( // IgnorePointer so that GestureDetector can be used above the platform view. From 87e76ac3a5d4a27a83f1c9e49fb01c3cf7fc266d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 14:36:54 +0100 Subject: [PATCH 034/167] Unregister texture from registry only when using texture approach --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 5 +++-- 1 file changed, 3 insertions(+), 2 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 a1b57b0b233..23eea5d83e2 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 @@ -189,8 +189,9 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options - (void)disposePlayer:(NSInteger)textureId error:(FlutterError **)error { NSNumber *playerKey = @(textureId); FVPVideoPlayer *player = self.playersByTextureId[playerKey]; - // FIXME Only unregister texture when using texture approach - [self.registry unregisterTexture:textureId]; + if ([player isKindOfClass:[FVPVideoPlayerTextureApproach class]]) { + [self.registry unregisterTexture:textureId]; + } [self.playersByTextureId removeObjectForKey:playerKey]; if (!player.disposed) { [player dispose]; From 4d11c11344c9f1048079e228aea26928a1a6de4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 14:37:26 +0100 Subject: [PATCH 035/167] Clean up code, add more context in comments --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 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 23eea5d83e2..cefa1a8cc1d 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 @@ -18,6 +18,7 @@ #import "./include/video_player_avfoundation/messages.g.h" #if TARGET_OS_IOS +// Platform views are only supported on iOS as of now. #import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #endif @@ -52,6 +53,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; #if TARGET_OS_IOS + // Platform views are only supported on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger playersByTextureId:instance.playersByTextureId]; @@ -87,11 +89,14 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { + // FIXME Rename textureId to playerId, in all other places as well. int64_t textureId; - if (frameUpdater != nil) { + if (frameUpdater) { textureId = [self.registry registerTexture:player]; frameUpdater.textureId = textureId; } else { + // FIXME Possibly start with a predefined prefix and then increment it to avoid + // collisions withtextureId. textureId = arc4random(); } @@ -104,7 +109,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater self.playersByTextureId[@(textureId)] = player; // FIXME Does it need to be here? - if (frameUpdater != nil) { + if (frameUpdater) { // Ensure that the first frame is drawn once available, even if the video isn't played, since // the engine is now expecting the texture to be populated. // We can safely cast to FVPVideoPlayerTextureApproach since frameUpdater is non-nil. From d4dc7e5440b0f9a308581c0aac4d609df3d39454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 17:27:57 +0100 Subject: [PATCH 036/167] Fix most of existing unit tests by creating a player with texture view approach, like it happened up to this point --- .../darwin/RunnerTests/VideoPlayerTests.m | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) 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 02b9199a74f..036897a213f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -179,7 +179,9 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -217,7 +219,9 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -283,7 +287,9 @@ - (void)testInitStartsDisplayLinkTemporarily { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -333,7 +339,9 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -395,7 +403,9 @@ - (void)testPauseWhileWaitingForFrameDoesNotStopDisplayLink { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -423,7 +433,9 @@ - (void)testDeregistersFromPlayer { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -455,7 +467,9 @@ - (void)testBufferingStateFromPlayer { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -564,7 +578,9 @@ - (void)testSeekToleranceWhenNotSeekingToEnd { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; @@ -602,7 +618,9 @@ - (void)testSeekToleranceWhenSeekingToEnd { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; FlutterError *createError; NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; @@ -625,11 +643,14 @@ - (void)testSeekToleranceWhenSeekingToEnd { [videoPlayerPlugin initialize:&error]; XCTAssertNil(error); - FVPCreationOptions *create = [FVPCreationOptions makeWithAsset:nil - uri:uri - packageName:nil - formatHint:nil - httpHeaders:@{}]; + FVPCreationOptions *create = + [FVPCreationOptions makeWithAsset:nil + uri:uri + packageName:nil + formatHint:nil + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; @@ -694,7 +715,9 @@ - (void)testDoesNotCrashOnRateObservationAfterDisposal { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -748,7 +771,9 @@ - (void)testHotReloadDoesNotCrash { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -782,6 +807,8 @@ - (void)testPublishesInRegistration { NSObject *registry = GetPluginRegistry(); NSObject *registrar = [registry registrarForPlugin:pluginKey]; + // FIXME This line makes the test fail (or rather run forever) if native view factory is + // registered. [FVPVideoPlayerPlugin registerWithRegistrar:registrar]; id publishedValue = [registry valuePublishedByPlugin:pluginKey]; From 73564c73b3a11e9b533d5c7e1021b7737ec0ec2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 19 Nov 2024 18:18:15 +0100 Subject: [PATCH 037/167] Check platform view in UI test --- .../ios/RunnerUITests/VideoPlayerUITests.m | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m index 54c97030c3a..778caa0c308 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m @@ -21,30 +21,39 @@ - (void)setUp { - (void)testPlayVideo { XCUIApplication *app = self.app; - - XCUIElement *remoteTab = [app.otherElements - elementMatchingPredicate:[NSPredicate predicateWithFormat:@"selected == YES"]]; + XCUIElement *remoteTab = + [[app.otherElements matchingPredicate:[NSPredicate predicateWithFormat:@"selected == YES"]] + elementBoundByIndex:0]; XCTAssertTrue([remoteTab waitForExistenceWithTimeout:30.0]); XCTAssertTrue([remoteTab.label containsString:@"Remote"]); - XCUIElement *playButton = app.staticTexts[@"Play"]; - XCTAssertTrue([playButton waitForExistenceWithTimeout:30.0]); - [playButton tap]; + // FIXME Is this a good way to check platform view? + for (NSString *tabName in @[ @"Platform view", @"Texture view" ]) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label BEGINSWITH %@", tabName]; + XCUIElement *viewTypeTab = [app.staticTexts elementMatchingPredicate:predicate]; + XCTAssertTrue([viewTypeTab waitForExistenceWithTimeout:30.0]); + XCTAssertFalse(viewTypeTab.isSelected); + [viewTypeTab tap]; + + XCUIElement *playButton = app.staticTexts[@"Play"]; + XCTAssertTrue([playButton waitForExistenceWithTimeout:30.0]); + [playButton tap]; - NSPredicate *find1xButton = [NSPredicate predicateWithFormat:@"label CONTAINS '1.0x'"]; - XCUIElement *playbackSpeed1x = [app.staticTexts elementMatchingPredicate:find1xButton]; - BOOL foundPlaybackSpeed1x = [playbackSpeed1x waitForExistenceWithTimeout:30.0]; - XCTAssertTrue(foundPlaybackSpeed1x); - [playbackSpeed1x tap]; + NSPredicate *find1xButton = [NSPredicate predicateWithFormat:@"label CONTAINS '1.0x'"]; + XCUIElement *playbackSpeed1x = [app.staticTexts elementMatchingPredicate:find1xButton]; + BOOL foundPlaybackSpeed1x = [playbackSpeed1x waitForExistenceWithTimeout:30.0]; + XCTAssertTrue(foundPlaybackSpeed1x); + [playbackSpeed1x tap]; - XCUIElement *playbackSpeed5xButton = app.buttons[@"5.0x"]; - XCTAssertTrue([playbackSpeed5xButton waitForExistenceWithTimeout:30.0]); - [playbackSpeed5xButton tap]; + XCUIElement *playbackSpeed5xButton = app.buttons[@"5.0x"]; + XCTAssertTrue([playbackSpeed5xButton waitForExistenceWithTimeout:30.0]); + [playbackSpeed5xButton tap]; - NSPredicate *find5xButton = [NSPredicate predicateWithFormat:@"label CONTAINS '5.0x'"]; - XCUIElement *playbackSpeed5x = [app.staticTexts elementMatchingPredicate:find5xButton]; - BOOL foundPlaybackSpeed5x = [playbackSpeed5x waitForExistenceWithTimeout:30.0]; - XCTAssertTrue(foundPlaybackSpeed5x); + NSPredicate *find5xButton = [NSPredicate predicateWithFormat:@"label CONTAINS '5.0x'"]; + XCUIElement *playbackSpeed5x = [app.staticTexts elementMatchingPredicate:find5xButton]; + BOOL foundPlaybackSpeed5x = [playbackSpeed5x waitForExistenceWithTimeout:30.0]; + XCTAssertTrue(foundPlaybackSpeed5x); + } // Cycle through tabs. for (NSString *tabName in @[ @"Asset mp4", @"Remote mp4" ]) { From 30f65c051a762a7caa2da3fe32d947674d6df49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 10:32:33 +0100 Subject: [PATCH 038/167] Only allow choosing between texture view and platform view in example on iOS --- .../example/lib/main.dart | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index e043e05b882..d195f91a9b5 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -4,6 +4,8 @@ // ignore_for_file: public_member_api_docs +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -42,20 +44,27 @@ class _App extends StatelessWidget { ), ), body: TabBarView( - children: [ - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _BumbleBeeRemoteVideo(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _BumbleBeeEncryptedLiveStream(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _ButterFlyAssetVideo(viewType), - ), - ], + children: Platform.isIOS + ? [ + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeRemoteVideo(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeEncryptedLiveStream(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _ButterFlyAssetVideo(viewType), + ), + ] + // We don't support platform views on MacOS yet. + : const [ + _BumbleBeeRemoteVideo(VideoViewType.textureView), + _BumbleBeeEncryptedLiveStream(VideoViewType.textureView), + _ButterFlyAssetVideo(VideoViewType.textureView), + ], ), ), ); From 3cd512672f11ed84ad833bd533310018eadaec85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 10:59:20 +0100 Subject: [PATCH 039/167] Only include native view files on iOS --- .../darwin/video_player_avfoundation.podspec | 1 + .../FVPVideoPlayerPlugin.m | 2 +- .../FVPNativeVideoView.m | 2 +- .../FVPNativeVideoViewFactory.m | 7 ++++--- .../include}/FVPNativeVideoView.h | 20 +++++-------------- .../include}/FVPNativeVideoViewFactory.h | 4 ---- 6 files changed, 12 insertions(+), 24 deletions(-) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation/include/video_player_avfoundation => video_player_avfoundation_ios/include}/FVPNativeVideoView.h (63%) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation/include/video_player_avfoundation => video_player_avfoundation_ios/include}/FVPNativeVideoViewFactory.h (88%) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec index 81e8d2f8e4e..94281a6dc0d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec @@ -18,6 +18,7 @@ Downloaded by pub (not CocoaPods). s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/*' s.osx.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_macos/*' s.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation/include/**/*.h' + s.ios.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/include/*.h' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' 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 cefa1a8cc1d..848d0ea5116 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 @@ -19,7 +19,7 @@ #if TARGET_OS_IOS // Platform views are only supported on iOS as of now. -#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" +#import "../video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h" #endif #if !__has_feature(objc_arc) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index f8050466ec3..1ad0994b864 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -4,7 +4,7 @@ #import -#import "FVPNativeVideoView.h" +#import "./include/FVPNativeVideoView.h" // FIXME Add some docs for FVPNativeVideoView and possibly FVPPlayerView @interface FVPPlayerView : UIView diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index be036f43296..fbc327dd354 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FVPNativeVideoViewFactory.h" -#import "FVPNativeVideoView.h" -#import "FVPVideoPlayer.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" + +#import "./include/FVPNativeVideoView.h" +#import "./include/FVPNativeVideoViewFactory.h" @implementation FVPNativeVideoViewFactory { NSObject *_messenger; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h similarity index 63% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h index 871ac36fcfa..daba6464189 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h @@ -2,29 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if TARGET_OS_OSX -#import -#else +// FIXME Do we even need if statement below? MacOS currently doesn't support +// FlutterPlatformView. +// But can we complie code without it? And is it good to put iOS-specific code +// in the main directory (video_player_avfoundation? + #import -#endif -// FIXME Do we even need ifs below? MacOS currently doesn't support FlutterPlatformView. -// But can we complie code without it? And is it good to put iOS-specific code in the main -// directory (video_player_avfoundation? -#if TARGET_OS_OSX -@interface FVPNativeVideoView : NSView -#else @interface FVPNativeVideoView : NSObject -#endif - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args binaryMessenger:(NSObject *)messenger player:(AVPlayer *)player; -#if TARGET_OS_OSX -- (NSView *)view; -#else - (UIView *)view; -#endif @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h similarity index 88% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h index 64fb7c7a1f8..fe04fd2967f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h @@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if TARGET_OS_OSX -#import -#else #import -#endif #import "FVPVideoPlayer.h" From c96ca17e2356943ed00ea800481750729d0e08c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 13:05:35 +0100 Subject: [PATCH 040/167] Make comments less ambiguous --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 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 848d0ea5116..04a195cacc8 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 @@ -18,7 +18,7 @@ #import "./include/video_player_avfoundation/messages.g.h" #if TARGET_OS_IOS -// Platform views are only supported on iOS as of now. +// We only support platform views on iOS as of now. #import "../video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h" #endif @@ -53,7 +53,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; #if TARGET_OS_IOS - // Platform views are only supported on iOS as of now. + // We only support platform views on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger playersByTextureId:instance.playersByTextureId]; From c26b210ef9d3de4f50f1fa7e810973e0defe13f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 13:07:05 +0100 Subject: [PATCH 041/167] Add unit tests for factory registration and lack of texture registration for platform view --- .../darwin/RunnerTests/VideoPlayerTests.m | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) 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 036897a213f..afa3eaeb4cb 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -192,6 +192,42 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom XCTAssertNotNil(player.playerLayer.superlayer, @"AVPlayerLayer should be added on screen."); } +- (void)testPlayerForPlatformViewDoesNotRegisterTexture { + NSObject *mockTextureRegistry = + OCMProtocolMock(@protocol(FlutterTextureRegistry)); + NSObject *registrar = + [GetPluginRegistry() registrarForPlugin:@"testPlayerTypeForPlatformView"]; + NSObject *partialRegistrar = OCMPartialMock(registrar); + OCMStub([partialRegistrar textures]).andReturn(mockTextureRegistry); + FVPDisplayLink *mockDisplayLink = + OCMPartialMock([[FVPDisplayLink alloc] initWithRegistrar:registrar + callback:^(){ + }]); + StubFVPDisplayLinkFactory *stubDisplayLinkFactory = + [[StubFVPDisplayLinkFactory alloc] initWithDisplayLink:mockDisplayLink]; + AVPlayerItemVideoOutput *mockVideoOutput = OCMPartialMock([[AVPlayerItemVideoOutput alloc] init]); + FVPVideoPlayerPlugin *videoPlayerPlugin = [[FVPVideoPlayerPlugin alloc] + initWithAVFactory:[[StubFVPAVFactory alloc] initWithPlayer:nil output:mockVideoOutput] + displayLinkFactory:stubDisplayLinkFactory + registrar:partialRegistrar]; + + FlutterError *initalizationError; + [videoPlayerPlugin initialize:&initalizationError]; + XCTAssertNil(initalizationError); + FVPCreationOptions *create = [FVPCreationOptions + makeWithAsset:nil + uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8" + packageName:nil + formatHint:nil + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypePlatformView]]; + FlutterError *createError; + [videoPlayerPlugin createWithOptions:create error:&createError]; + + OCMVerify(never(), [mockTextureRegistry registerTexture:[OCMArg any]]); +} + - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { NSObject *mockTextureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry)); @@ -802,6 +838,21 @@ - (void)testHotReloadDoesNotCrash { handler:nil]; // No assertions needed. Lack of crash is a success. } +#if TARGET_OS_IOS +- (void)testNativeVideoViewFactoryRegistration { + NSObject *registrar = + [GetPluginRegistry() registrarForPlugin:@"testNativeVideoViewFactoryRegistration"]; + id mockRegistrar = OCMPartialMock(registrar); + + OCMExpect([mockRegistrar + registerViewFactory:[OCMArg isKindOfClass:[FVPNativeVideoViewFactory class]] + withId:@"plugins.flutter.dev/video_player_ios"]); + [FVPVideoPlayerPlugin registerWithRegistrar:mockRegistrar]; + + OCMVerifyAll(mockRegistrar); +} +#endif + - (void)testPublishesInRegistration { NSString *pluginKey = @"TestRegistration"; NSObject *registry = GetPluginRegistry(); From 45862e3640a04713862f0d22e145820ae804a514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 13:21:05 +0100 Subject: [PATCH 042/167] Make viewType an optional parameter and default to textureView --- .../example/lib/mini_controller.dart | 24 ++++++++++++------- .../lib/src/avfoundation_video_player.dart | 6 ++--- .../lib/video_player_platform_interface.dart | 5 +++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index bf08307e1d8..9150255ac3f 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -167,20 +167,27 @@ class MiniController extends ValueNotifier { /// The name of the asset is given by the [dataSource] argument and must not be /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. - MiniController.asset(this.dataSource, {this.package, required this.viewType}) - : dataSourceType = DataSourceType.asset, + MiniController.asset( + this.dataSource, { + this.package, + this.viewType = VideoViewType.textureView, + }) : dataSourceType = DataSourceType.asset, super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [MiniController] playing a video from obtained from /// the network. - MiniController.network(this.dataSource, {required this.viewType}) - : dataSourceType = DataSourceType.network, + MiniController.network( + this.dataSource, { + this.viewType = VideoViewType.textureView, + }) : dataSourceType = DataSourceType.network, package = null, super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [MiniController] playing a video from obtained from a file. - MiniController.file(File file, {required this.viewType}) - : dataSource = Uri.file(file.absolute.path).toString(), + MiniController.file( + File file, { + this.viewType = VideoViewType.textureView, + }) : dataSource = Uri.file(file.absolute.path).toString(), dataSourceType = DataSourceType.file, package = null, super(const VideoPlayerValue(duration: Duration.zero)); @@ -242,8 +249,9 @@ class MiniController extends ValueNotifier { ); } - _textureId = (await _platform.create(dataSourceDescription, viewType)) ?? - kUninitializedTextureId; + _textureId = + (await _platform.create(dataSourceDescription, viewType: viewType)) ?? + kUninitializedTextureId; _creatingCompleter!.complete(null); final Completer initializingCompleter = Completer(); diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index f1fd6fb4274..43186863ca2 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -33,9 +33,9 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future create( - DataSource dataSource, - VideoViewType viewType, - ) async { + DataSource dataSource, { + VideoViewType viewType = VideoViewType.textureView, + }) async { String? asset; String? packageName; String? uri; diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index dbd8921b5f9..8cd94f4e829 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -49,7 +49,10 @@ abstract class VideoPlayerPlatform extends PlatformInterface { } /// Creates an instance of a video player and returns its textureId. - Future create(DataSource dataSource, VideoViewType viewType) { + Future create( + DataSource dataSource, { + VideoViewType viewType = VideoViewType.textureView, + }) { throw UnimplementedError('create() has not been implemented.'); } From 479dc372ae597c6c82b34a3b0e37ad3b5575b860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 13:42:41 +0100 Subject: [PATCH 043/167] Document new classes in native iOS code --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 1 - .../FVPVideoPlayerTextureApproach.h | 4 +++- .../video_player_avfoundation_ios/FVPNativeVideoView.m | 1 - .../include/FVPNativeVideoView.h | 10 +++++----- 4 files changed, 8 insertions(+), 8 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 04a195cacc8..1faf83b99d0 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 @@ -108,7 +108,6 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater player.eventChannel = eventChannel; self.playersByTextureId[@(textureId)] = player; - // FIXME Does it need to be here? if (frameUpdater) { // Ensure that the first frame is drawn once available, even if the video isn't played, since // the engine is now expecting the texture to be populated. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index bfad965a4a3..96d926e941f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -6,7 +6,9 @@ #import "FVPFrameUpdater.h" #import "FVPVideoPlayer.h" -// FIXME Add docs - what functionality this class adds. +/// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of +/// displaying the video in the app. It manages the CALayer associated with the Flutter view, +/// updates frames, and handles display link callbacks. @interface FVPVideoPlayerTextureApproach : FVPVideoPlayer // The CALayer associated with the Flutter view this plugin is associated with, if any. @property(nonatomic, readonly) CALayer *flutterViewLayer; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 1ad0994b864..771aa8b1a82 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -6,7 +6,6 @@ #import "./include/FVPNativeVideoView.h" -// FIXME Add some docs for FVPNativeVideoView and possibly FVPPlayerView @interface FVPPlayerView : UIView @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h index daba6464189..f850c5346e6 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// FIXME Do we even need if statement below? MacOS currently doesn't support -// FlutterPlatformView. -// But can we complie code without it? And is it good to put iOS-specific code -// in the main directory (video_player_avfoundation? - #import +/// A class used to create a native video view that can be embedded in a Flutter app. +/// This class wraps an AVPlayer instance and displays its video content. @interface FVPNativeVideoView : NSObject +/// Initializes a new instance of a native view. +/// It creates a video view instance and sets the provided AVPlayer instance to it. - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args binaryMessenger:(NSObject *)messenger player:(AVPlayer *)player; +/// Returns the native UIView that displays the video content. - (UIView *)view; @end From 7fe29f7cacbee8c3f7cbbaed90334f795823a45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 14:00:49 +0100 Subject: [PATCH 044/167] Document VideoViewType on Dart side --- .../example/lib/mini_controller.dart | 2 +- .../lib/video_player_platform_interface.dart | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index 9150255ac3f..e00929610f8 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -203,7 +203,7 @@ class MiniController extends ValueNotifier { /// Only set for [asset] videos. The package that the asset was loaded from. final String? package; - // FIXME Document + /// The type of view used to display the video. final VideoViewType viewType; Timer? _timer; diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 8cd94f4e829..7b080e3edcf 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -114,9 +114,12 @@ abstract class VideoPlayerPlatform extends PlatformInterface { class _PlaceholderImplementation extends VideoPlayerPlatform {} -// FIXME Add docs +/// Enum representing the type of video view to be used. enum VideoViewType { + /// Uses a texture view for rendering video. textureView, + + /// Uses a platform view for rendering video. platformView, } From 7f19bd13d57f3d0a63ee50eab303df80288c1a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 14:45:50 +0100 Subject: [PATCH 045/167] Fix variable name --- .../video_player_avfoundation_ios/FVPNativeVideoViewFactory.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index fbc327dd354..01f715c21a0 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -25,8 +25,8 @@ - (instancetype)initWithMessenger:(NSObject *)messenger - (NSObject *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { - NSNumber *viewIdFromArgs = args[@"playerId"]; - FVPVideoPlayer *player = _playersByTextureId[viewIdFromArgs]; + NSNumber *playerId = args[@"playerId"]; + FVPVideoPlayer *player = _playersByTextureId[playerId]; return [[FVPNativeVideoView alloc] initWithFrame:frame viewIdentifier:viewId arguments:args From f3eb9ea1e6e979ce2b354e54c3d6d6be4fc8e083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 17:05:12 +0100 Subject: [PATCH 046/167] Format files generated by pigeon --- .../video_player_avfoundation/messages.g.m | 6 +- .../lib/src/messages.g.dart | 111 +++++--- .../test/test_api.g.dart | 253 ++++++++++++------ 3 files changed, 238 insertions(+), 132 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index 255fbd8bbba..5b238679a22 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -4,16 +4,14 @@ // Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon +#import "./include/video_player_avfoundation/messages.g.h" + #if TARGET_OS_OSX #import #else #import #endif -// Relative path is needed for messages.g.h. See: -// https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 -#import "./include/video_player_avfoundation/messages.g.h" - #if !__has_feature(objc_arc) #error File requires ARC to be enabled. #endif diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index 39c988dec63..3775c094e02 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -18,7 +18,8 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -74,13 +75,13 @@ class CreationOptions { uri: result[1] as String?, packageName: result[2] as String?, formatHint: result[3] as String?, - httpHeaders: (result[4] as Map?)!.cast(), + httpHeaders: + (result[4] as Map?)!.cast(), viewType: result[5] as PlatformVideoViewType?, ); } } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -88,10 +89,10 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is PlatformVideoViewType) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is CreationOptions) { + } else if (value is CreationOptions) { buffer.putUint8(130); writeValue(buffer, value.encode()); } else { @@ -102,10 +103,10 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformVideoViewType.values[value]; - case 130: + case 130: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -117,9 +118,11 @@ class AVFoundationVideoPlayerApi { /// Constructor for [AVFoundationVideoPlayerApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - AVFoundationVideoPlayerApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + AVFoundationVideoPlayerApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -127,8 +130,10 @@ class AVFoundationVideoPlayerApi { final String pigeonVar_messageChannelSuffix; Future initialize() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -149,14 +154,16 @@ class AVFoundationVideoPlayerApi { } Future create(CreationOptions creationOptions) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([creationOptions]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([creationOptions]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -176,8 +183,10 @@ class AVFoundationVideoPlayerApi { } Future dispose(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -198,14 +207,16 @@ class AVFoundationVideoPlayerApi { } Future setLooping(bool isLooping, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([isLooping, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([isLooping, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -220,14 +231,16 @@ class AVFoundationVideoPlayerApi { } Future setVolume(double volume, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([volume, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([volume, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -242,14 +255,16 @@ class AVFoundationVideoPlayerApi { } Future setPlaybackSpeed(double speed, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([speed, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([speed, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -264,8 +279,10 @@ class AVFoundationVideoPlayerApi { } Future play(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -286,8 +303,10 @@ class AVFoundationVideoPlayerApi { } Future getPosition(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -313,14 +332,16 @@ class AVFoundationVideoPlayerApi { } Future seekTo(int position, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([position, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([position, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -335,8 +356,10 @@ class AVFoundationVideoPlayerApi { } Future pause(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -357,14 +380,16 @@ class AVFoundationVideoPlayerApi { } Future setMixWithOthers(bool mixWithOthers) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([mixWithOthers]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([mixWithOthers]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { diff --git a/packages/video_player/video_player_avfoundation/test/test_api.g.dart b/packages/video_player/video_player_avfoundation/test/test_api.g.dart index b888c96aa98..c65a595e4f7 100644 --- a/packages/video_player/video_player_avfoundation/test/test_api.g.dart +++ b/packages/video_player/video_player_avfoundation/test/test_api.g.dart @@ -13,7 +13,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:video_player_avfoundation/src/messages.g.dart'; - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -21,10 +20,10 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is PlatformVideoViewType) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is CreationOptions) { + } else if (value is CreationOptions) { buffer.putUint8(130); writeValue(buffer, value.encode()); } else { @@ -35,10 +34,10 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformVideoViewType.values[value]; - case 130: + case 130: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -47,7 +46,8 @@ class _PigeonCodec extends StandardMessageCodec { } abstract class TestHostVideoPlayerApi { - static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); void initialize(); @@ -72,39 +72,58 @@ abstract class TestHostVideoPlayerApi { void setMixWithOthers(bool mixWithOthers); - static void setUp(TestHostVideoPlayerApi? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + TestHostVideoPlayerApi? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { try { api.initialize(); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null.'); final List args = (message as List?)!; - final CreationOptions? arg_creationOptions = (args[0] as CreationOptions?); + final CreationOptions? arg_creationOptions = + (args[0] as CreationOptions?); assert(arg_creationOptions != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create was null, expected non-null CreationOptions.'); try { @@ -112,22 +131,29 @@ abstract class TestHostVideoPlayerApi { return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -137,22 +163,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null.'); final List args = (message as List?)!; final bool? arg_isLooping = (args[0] as bool?); assert(arg_isLooping != null, @@ -165,22 +198,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null.'); final List args = (message as List?)!; final double? arg_volume = (args[0] as double?); assert(arg_volume != null, @@ -193,22 +233,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null.'); final List args = (message as List?)!; final double? arg_speed = (args[0] as double?); assert(arg_speed != null, @@ -221,22 +268,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -246,22 +300,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -271,22 +332,29 @@ abstract class TestHostVideoPlayerApi { return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null.'); final List args = (message as List?)!; final int? arg_position = (args[0] as int?); assert(arg_position != null, @@ -299,22 +367,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null.'); final List args = (message as List?)!; final int? arg_textureId = (args[0] as int?); assert(arg_textureId != null, @@ -324,22 +399,29 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$messageChannelSuffix', pigeonChannelCodec, + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers was null.'); + 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers was null.'); final List args = (message as List?)!; final bool? arg_mixWithOthers = (args[0] as bool?); assert(arg_mixWithOthers != null, @@ -349,8 +431,9 @@ abstract class TestHostVideoPlayerApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); } }); } From a28b580c61dbb9432bd93a3000339fc5eed78f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 20 Nov 2024 17:35:03 +0100 Subject: [PATCH 047/167] Use a class for platform view creation params --- .../video_player_avfoundation/messages.g.h | 9 + .../video_player_avfoundation/messages.g.m | 238 ++++++++---------- .../FVPNativeVideoView.m | 6 +- .../FVPNativeVideoViewFactory.m | 12 +- .../include/FVPNativeVideoView.h | 6 +- .../lib/src/avfoundation_video_player.dart | 8 +- .../lib/src/messages.g.dart | 138 +++++----- .../pigeons/messages.dart | 9 + .../test/test_api.g.dart | 7 +- 9 files changed, 206 insertions(+), 227 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h index 81c227e3c13..7f545d7575c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h @@ -25,8 +25,17 @@ typedef NS_ENUM(NSUInteger, FVPPlatformVideoViewType) { - (instancetype)initWithValue:(FVPPlatformVideoViewType)value; @end +@class FVPPlatformVideoViewCreationParams; @class FVPCreationOptions; +/// Information passed to the platform view creation. +@interface FVPPlatformVideoViewCreationParams : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithPlayerId:(NSInteger )playerId; +@property(nonatomic, assign) NSInteger playerId; +@end + @interface FVPCreationOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index 5b238679a22..3cf2c9d15bd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -41,20 +41,47 @@ - (instancetype)initWithValue:(FVPPlatformVideoViewType)value { } @end +@interface FVPPlatformVideoViewCreationParams () ++ (FVPPlatformVideoViewCreationParams *)fromList:(NSArray *)list; ++ (nullable FVPPlatformVideoViewCreationParams *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface FVPCreationOptions () + (FVPCreationOptions *)fromList:(NSArray *)list; + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list; - (NSArray *)toList; @end +@implementation FVPPlatformVideoViewCreationParams ++ (instancetype)makeWithPlayerId:(NSInteger )playerId { + FVPPlatformVideoViewCreationParams* pigeonResult = [[FVPPlatformVideoViewCreationParams alloc] init]; + pigeonResult.playerId = playerId; + return pigeonResult; +} ++ (FVPPlatformVideoViewCreationParams *)fromList:(NSArray *)list { + FVPPlatformVideoViewCreationParams *pigeonResult = [[FVPPlatformVideoViewCreationParams alloc] init]; + pigeonResult.playerId = [GetNullableObjectAtIndex(list, 0) integerValue]; + return pigeonResult; +} ++ (nullable FVPPlatformVideoViewCreationParams *)nullableFromList:(NSArray *)list { + return (list) ? [FVPPlatformVideoViewCreationParams fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + @(self.playerId), + ]; +} +@end + @implementation FVPCreationOptions + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { - FVPCreationOptions *pigeonResult = [[FVPCreationOptions alloc] init]; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { + FVPCreationOptions* pigeonResult = [[FVPCreationOptions alloc] init]; pigeonResult.asset = asset; pigeonResult.uri = uri; pigeonResult.packageName = packageName; @@ -95,11 +122,11 @@ - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 129: { NSNumber *enumAsNumber = [self readValue]; - return enumAsNumber == nil - ? nil - : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + return enumAsNumber == nil ? nil : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; } - case 130: + case 130: + return [FVPPlatformVideoViewCreationParams fromList:[self readValue]]; + case 131: return [FVPCreationOptions fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -115,9 +142,12 @@ - (void)writeValue:(id)value { FVPPlatformVideoViewTypeBox *box = (FVPPlatformVideoViewTypeBox *)value; [self writeByte:129]; [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; - } else if ([value isKindOfClass:[FVPCreationOptions class]]) { + } else if ([value isKindOfClass:[FVPPlatformVideoViewCreationParams class]]) { [self writeByte:130]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[FVPCreationOptions class]]) { + [self writeByte:131]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -139,35 +169,25 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ - FVPMessagesPigeonCodecReaderWriter *readerWriter = - [[FVPMessagesPigeonCodecReaderWriter alloc] init]; + FVPMessagesPigeonCodecReaderWriter *readerWriter = [[FVPMessagesPigeonCodecReaderWriter alloc] init]; sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; }); return sSharedObject; } -void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, - NSObject *api) { +void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *api) { SetUpFVPAVFoundationVideoPlayerApiWithSuffix(binaryMessenger, api, @""); } -void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, - NSObject *api, - NSString *messageChannelSuffix) { - messageChannelSuffix = messageChannelSuffix.length > 0 - ? [NSString stringWithFormat:@".%@", messageChannelSuffix] - : @""; +void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *api, NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 ? [NSString stringWithFormat: @".%@", messageChannelSuffix] : @""; { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.initialize", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(initialize:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", - api); + NSCAssert([api respondsToSelector:@selector(initialize:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { FlutterError *error; [api initialize:&error]; @@ -178,18 +198,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.create", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(createWithOptions:error:)", - api); + NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(createWithOptions:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; FVPCreationOptions *arg_creationOptions = GetNullableObjectAtIndex(args, 0); @@ -202,18 +217,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.dispose", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(disposePlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(disposePlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -226,18 +236,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setLooping", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setLooping:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setLooping:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_isLooping = [GetNullableObjectAtIndex(args, 0) boolValue]; @@ -251,18 +256,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setVolume", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setVolume:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setVolume:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_volume = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -276,18 +276,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setPlaybackSpeed", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setPlaybackSpeed:forPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setPlaybackSpeed:forPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_speed = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -301,18 +296,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.play", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert( - [api respondsToSelector:@selector(playPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(playPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -325,18 +315,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.getPosition", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(positionForPlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(positionForPlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -349,45 +334,33 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.seekTo", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(seekTo:forPlayer:completion:)", - api); + NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(seekTo:forPlayer:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_position = [GetNullableObjectAtIndex(args, 0) integerValue]; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; - [api seekTo:arg_position - forPlayer:arg_textureId - completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api seekTo:arg_position forPlayer:arg_textureId completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.pause", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(pausePlayer:error:)", - api); + NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(pausePlayer:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -400,18 +373,13 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.video_player_avfoundation." - @"AVFoundationVideoPlayerApi.setMixWithOthers", - messageChannelSuffix] + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], - @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " - @"@selector(setMixWithOthers:error:)", - api); + NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setMixWithOthers:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_mixWithOthers = [GetNullableObjectAtIndex(args, 0) boolValue]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 771aa8b1a82..14472cfc8b5 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -23,11 +23,7 @@ @implementation FVPNativeVideoView { FVPPlayerView *_view; } -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - binaryMessenger:(NSObject *)messenger - player:(AVPlayer *)player { +- (instancetype)initWithPlayer:(AVPlayer *)player { if (self = [super init]) { _view = [[FVPPlayerView alloc] init]; [_view setPlayer:player]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 01f715c21a0..c700c57203b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -24,17 +24,13 @@ - (instancetype)initWithMessenger:(NSObject *)messenger - (NSObject *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args { - NSNumber *playerId = args[@"playerId"]; + arguments:(FVPPlatformVideoViewCreationParams *)args { + NSNumber *playerId = @(args.playerId); FVPVideoPlayer *player = _playersByTextureId[playerId]; - return [[FVPNativeVideoView alloc] initWithFrame:frame - viewIdentifier:viewId - arguments:args - binaryMessenger:_messenger - player:player.player]; + return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; } - (NSObject *)createArgsCodec { - return [FlutterStandardMessageCodec sharedInstance]; + return FVPGetMessagesCodec(); } @end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h index f850c5346e6..ed5f4d6d157 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h @@ -9,11 +9,7 @@ @interface FVPNativeVideoView : NSObject /// Initializes a new instance of a native view. /// It creates a video view instance and sets the provided AVPlayer instance to it. -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - binaryMessenger:(NSObject *)messenger - player:(AVPlayer *)player; +- (instancetype)initWithPlayer:(AVPlayer *)player; /// Returns the native UIView that displays the video content. - (UIView *)view; diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 43186863ca2..e82d331dc22 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -158,16 +158,14 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } Widget _buildPlatformView(int playerId, VideoViewType viewType) { - // FIXME Use a separate class for creation params. - final Map creationParams = { - 'playerId': playerId, - }; + final PlatformVideoViewCreationParams creationParams = + PlatformVideoViewCreationParams(playerId: playerId); return IgnorePointer( // IgnorePointer so that GestureDetector can be used above the platform view. child: UiKitView( viewType: 'plugins.flutter.dev/video_player_ios', creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), + creationParamsCodec: AVFoundationVideoPlayerApi.pigeonChannelCodec, ), ); } diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index 3775c094e02..d69dc2136cd 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -18,8 +18,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -35,6 +34,28 @@ enum PlatformVideoViewType { platformView, } +/// Information passed to the platform view creation. +class PlatformVideoViewCreationParams { + PlatformVideoViewCreationParams({ + required this.playerId, + }); + + int playerId; + + Object encode() { + return [ + playerId, + ]; + } + + static PlatformVideoViewCreationParams decode(Object result) { + result as List; + return PlatformVideoViewCreationParams( + playerId: result[0]! as int, + ); + } +} + class CreationOptions { CreationOptions({ this.asset, @@ -75,13 +96,13 @@ class CreationOptions { uri: result[1] as String?, packageName: result[2] as String?, formatHint: result[3] as String?, - httpHeaders: - (result[4] as Map?)!.cast(), + httpHeaders: (result[4] as Map?)!.cast(), viewType: result[5] as PlatformVideoViewType?, ); } } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -89,12 +110,15 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is PlatformVideoViewType) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is CreationOptions) { + } else if (value is PlatformVideoViewCreationParams) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is CreationOptions) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -103,10 +127,12 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformVideoViewType.values[value]; - case 130: + case 130: + return PlatformVideoViewCreationParams.decode(readValue(buffer)!); + case 131: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -118,11 +144,9 @@ class AVFoundationVideoPlayerApi { /// Constructor for [AVFoundationVideoPlayerApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - AVFoundationVideoPlayerApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + AVFoundationVideoPlayerApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -130,10 +154,8 @@ class AVFoundationVideoPlayerApi { final String pigeonVar_messageChannelSuffix; Future initialize() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -154,16 +176,14 @@ class AVFoundationVideoPlayerApi { } Future create(CreationOptions creationOptions) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([creationOptions]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([creationOptions]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -183,10 +203,8 @@ class AVFoundationVideoPlayerApi { } Future dispose(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -207,16 +225,14 @@ class AVFoundationVideoPlayerApi { } Future setLooping(bool isLooping, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([isLooping, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([isLooping, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -231,16 +247,14 @@ class AVFoundationVideoPlayerApi { } Future setVolume(double volume, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([volume, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([volume, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -255,16 +269,14 @@ class AVFoundationVideoPlayerApi { } Future setPlaybackSpeed(double speed, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([speed, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([speed, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -279,10 +291,8 @@ class AVFoundationVideoPlayerApi { } Future play(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -303,10 +313,8 @@ class AVFoundationVideoPlayerApi { } Future getPosition(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -332,16 +340,14 @@ class AVFoundationVideoPlayerApi { } Future seekTo(int position, int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([position, textureId]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([position, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -356,10 +362,8 @@ class AVFoundationVideoPlayerApi { } Future pause(int textureId) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -380,16 +384,14 @@ class AVFoundationVideoPlayerApi { } Future setMixWithOthers(bool mixWithOthers) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([mixWithOthers]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([mixWithOthers]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { diff --git a/packages/video_player/video_player_avfoundation/pigeons/messages.dart b/packages/video_player/video_player_avfoundation/pigeons/messages.dart index 91190861f52..80fef03f860 100644 --- a/packages/video_player/video_player_avfoundation/pigeons/messages.dart +++ b/packages/video_player/video_player_avfoundation/pigeons/messages.dart @@ -24,6 +24,15 @@ enum PlatformVideoViewType { platformView, } +/// Information passed to the platform view creation. +class PlatformVideoViewCreationParams { + const PlatformVideoViewCreationParams({ + required this.playerId, + }); + + final int playerId; +} + class CreationOptions { CreationOptions({required this.httpHeaders}); String? asset; diff --git a/packages/video_player/video_player_avfoundation/test/test_api.g.dart b/packages/video_player/video_player_avfoundation/test/test_api.g.dart index c65a595e4f7..5fc69e63ccd 100644 --- a/packages/video_player/video_player_avfoundation/test/test_api.g.dart +++ b/packages/video_player/video_player_avfoundation/test/test_api.g.dart @@ -23,9 +23,12 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is PlatformVideoViewType) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is CreationOptions) { + } else if (value is PlatformVideoViewCreationParams) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is CreationOptions) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -38,6 +41,8 @@ class _PigeonCodec extends StandardMessageCodec { final int? value = readValue(buffer) as int?; return value == null ? null : PlatformVideoViewType.values[value]; case 130: + return PlatformVideoViewCreationParams.decode(readValue(buffer)!); + case 131: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); From da768fe4b8370fef9647cddadb9b5ec9d86ee0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 08:53:41 +0100 Subject: [PATCH 048/167] Remove unused param from method --- .../lib/src/avfoundation_video_player.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index e82d331dc22..7fadd3258d5 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -153,11 +153,11 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { Widget buildView(int textureId, VideoViewType viewType) { return switch (viewType) { VideoViewType.textureView => Texture(textureId: textureId), - VideoViewType.platformView => _buildPlatformView(textureId, viewType), + VideoViewType.platformView => _buildPlatformView(textureId), }; } - Widget _buildPlatformView(int playerId, VideoViewType viewType) { + Widget _buildPlatformView(int playerId) { final PlatformVideoViewCreationParams creationParams = PlatformVideoViewCreationParams(playerId: playerId); return IgnorePointer( From dd5637ca4f4b1637a9f838c804263193543e2919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 12:01:38 +0100 Subject: [PATCH 049/167] Fix failing unit test, prevent double factory registration --- .../darwin/RunnerTests/VideoPlayerTests.m | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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 afa3eaeb4cb..ac018f75014 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -840,8 +840,9 @@ - (void)testHotReloadDoesNotCrash { #if TARGET_OS_IOS - (void)testNativeVideoViewFactoryRegistration { + NSObject *registry = GetPluginRegistry(); NSObject *registrar = - [GetPluginRegistry() registrarForPlugin:@"testNativeVideoViewFactoryRegistration"]; + [registry registrarForPlugin:@"testNativeVideoViewFactoryRegistration"]; id mockRegistrar = OCMPartialMock(registrar); OCMExpect([mockRegistrar @@ -857,10 +858,14 @@ - (void)testPublishesInRegistration { NSString *pluginKey = @"TestRegistration"; NSObject *registry = GetPluginRegistry(); NSObject *registrar = [registry registrarForPlugin:pluginKey]; + id mockRegistrar = OCMPartialMock(registrar); + // Empty stub to pass a check in Flutter's engine (double factory registration). + // registerWithRegistrar gets called at the beginning of the test, and factory is registered + // there. Additional call would try to register the same factory another time, which would fail a + // check in the engine. + OCMStub([mockRegistrar registerViewFactory:[OCMArg any] withId:[OCMArg any]]); - // FIXME This line makes the test fail (or rather run forever) if native view factory is - // registered. - [FVPVideoPlayerPlugin registerWithRegistrar:registrar]; + [FVPVideoPlayerPlugin registerWithRegistrar:mockRegistrar]; id publishedValue = [registry valuePublishedByPlugin:pluginKey]; From 5214aa571cc1b73e3fa79f2a8b1795e5ce9b3d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 12:27:56 +0100 Subject: [PATCH 050/167] Format pigeon generated file --- .../lib/src/messages.g.dart | 115 +++++++++++------- 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index d69dc2136cd..1b3f0e08950 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -18,7 +18,8 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -96,13 +97,13 @@ class CreationOptions { uri: result[1] as String?, packageName: result[2] as String?, formatHint: result[3] as String?, - httpHeaders: (result[4] as Map?)!.cast(), + httpHeaders: + (result[4] as Map?)!.cast(), viewType: result[5] as PlatformVideoViewType?, ); } } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -110,13 +111,13 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is PlatformVideoViewType) { + } else if (value is PlatformVideoViewType) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is PlatformVideoViewCreationParams) { + } else if (value is PlatformVideoViewCreationParams) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is CreationOptions) { + } else if (value is CreationOptions) { buffer.putUint8(131); writeValue(buffer, value.encode()); } else { @@ -127,12 +128,12 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformVideoViewType.values[value]; - case 130: + case 130: return PlatformVideoViewCreationParams.decode(readValue(buffer)!); - case 131: + case 131: return CreationOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -144,9 +145,11 @@ class AVFoundationVideoPlayerApi { /// Constructor for [AVFoundationVideoPlayerApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - AVFoundationVideoPlayerApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + AVFoundationVideoPlayerApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -154,8 +157,10 @@ class AVFoundationVideoPlayerApi { final String pigeonVar_messageChannelSuffix; Future initialize() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -176,14 +181,16 @@ class AVFoundationVideoPlayerApi { } Future create(CreationOptions creationOptions) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([creationOptions]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([creationOptions]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -203,8 +210,10 @@ class AVFoundationVideoPlayerApi { } Future dispose(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -225,14 +234,16 @@ class AVFoundationVideoPlayerApi { } Future setLooping(bool isLooping, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([isLooping, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([isLooping, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -247,14 +258,16 @@ class AVFoundationVideoPlayerApi { } Future setVolume(double volume, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([volume, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([volume, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -269,14 +282,16 @@ class AVFoundationVideoPlayerApi { } Future setPlaybackSpeed(double speed, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([speed, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([speed, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -291,8 +306,10 @@ class AVFoundationVideoPlayerApi { } Future play(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -313,8 +330,10 @@ class AVFoundationVideoPlayerApi { } Future getPosition(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -340,14 +359,16 @@ class AVFoundationVideoPlayerApi { } Future seekTo(int position, int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([position, textureId]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([position, textureId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -362,8 +383,10 @@ class AVFoundationVideoPlayerApi { } Future pause(int textureId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -384,14 +407,16 @@ class AVFoundationVideoPlayerApi { } Future setMixWithOthers(bool mixWithOthers) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + final String pigeonVar_channelName = + 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([mixWithOthers]) as List?; + final List? pigeonVar_replyList = await pigeonVar_channel + .send([mixWithOthers]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { From 981eb8a8503ec320a6d7d18ab7f4950980fc7868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 21 Nov 2024 13:05:52 +0100 Subject: [PATCH 051/167] Use correct plugin key in test function --- .../darwin/RunnerTests/VideoPlayerTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ac018f75014..2ef43ad0be7 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -196,7 +196,7 @@ - (void)testPlayerForPlatformViewDoesNotRegisterTexture { NSObject *mockTextureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry)); NSObject *registrar = - [GetPluginRegistry() registrarForPlugin:@"testPlayerTypeForPlatformView"]; + [GetPluginRegistry() registrarForPlugin:@"testPlayerForPlatformViewDoesNotRegisterTexture"]; NSObject *partialRegistrar = OCMPartialMock(registrar); OCMStub([partialRegistrar textures]).andReturn(mockTextureRegistry); FVPDisplayLink *mockDisplayLink = From 85d5ac616d1fe03f0312434d59ef0f18e2031f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 22 Nov 2024 11:21:53 +0100 Subject: [PATCH 052/167] Update dartdocs and comments --- .../lib/src/avfoundation_video_player.dart | 2 +- .../lib/video_player_platform_interface.dart | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 7fadd3258d5..ad9672aaf82 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -25,7 +25,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { return _api.initialize(); } - // FIXME Rename textureId everywhere to playerId. + // FIXME Rename textureId to playerId everywhere. @override Future dispose(int textureId) { return _api.dispose(textureId); diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 7b080e3edcf..54325a2598a 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -48,7 +48,9 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('dispose() has not been implemented.'); } - /// Creates an instance of a video player and returns its textureId. + /// Creates an instance of a video player with and returns its textureId. + /// The [viewType] parameter specifies the type of view to be used for the + /// video player. Future create( DataSource dataSource, { VideoViewType viewType = VideoViewType.textureView, @@ -96,7 +98,8 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('getPosition() has not been implemented.'); } - /// Returns a widget displaying the video with a given textureID. + /// Returns a widget displaying the video with a given textureID, using given + /// viewType. Widget buildView(int textureId, VideoViewType viewType) { throw UnimplementedError('buildView() has not been implemented.'); } From 97490aeb5f2ec213cfa0f8388c84c9d9f42d1220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 25 Nov 2024 16:18:49 +0100 Subject: [PATCH 053/167] Adjust FVPVideoPlayer interface after rebase --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index b8e66c22ce8..7f40d4c0b23 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN /// notify the Flutter engine about new video frames. @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. -@property(nonatomic) FlutterEventChannel *eventChannel; +@property(nonatomic, nonnull) FlutterEventChannel *eventChannel; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @@ -29,11 +29,11 @@ NS_ASSUME_NONNULL_BEGIN /// The current playback position of the video, in milliseconds. @property(readonly, nonatomic) int64_t position; +NS_ASSUME_NONNULL_BEGIN + /// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, /// HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory registrar:(NSObject *)registrar; @@ -41,16 +41,12 @@ NS_ASSUME_NONNULL_BEGIN /// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display /// link, AV factory, and registrar. - (instancetype)initWithPlayerItem:(AVPlayerItem *)item - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar; /// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, /// AV factory, and registrar. - (instancetype)initWithAsset:(NSString *)asset - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar; From fd777bd0c70cf56402ba2b644cdcc25d21640d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 25 Nov 2024 16:40:23 +0100 Subject: [PATCH 054/167] Fix Xcode analysis issues --- .../video_player_avfoundation/FVPVideoPlayer.m | 1 - .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 7 ++++--- .../video_player_avfoundation/FVPVideoPlayer.h | 4 ++++ .../FVPVideoPlayerTextureApproach.h | 12 ++++++++---- .../FVPNativeVideoViewFactory.m | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 97e496ad66f..fb020cda3db 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -382,7 +382,6 @@ - (int64_t)duration { } - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { - CMTime previousCMTime = _player.currentTime; CMTime targetCMTime = CMTimeMake(location, 1000); CMTimeValue duration = _player.currentItem.asset.duration.value; // Without adding tolerance when seeking to duration, 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 1faf83b99d0..6df570d388e 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 @@ -134,9 +134,10 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options error:(FlutterError **)error { + BOOL usesTextureApproach = options.viewType.value == FVPPlatformVideoViewTypeTextureView; FVPFrameUpdater *frameUpdater; FVPDisplayLink *displayLink; - if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + if (usesTextureApproach) { frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; displayLink = [self.displayLinkFactory displayLinkWithRegistrar:_registrar callback:^() { @@ -153,7 +154,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options assetPath = [_registrar lookupKeyForAsset:options.asset]; } @try { - if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + if (usesTextureApproach) { player = [[FVPVideoPlayerTextureApproach alloc] initWithAsset:assetPath frameUpdater:frameUpdater displayLink:displayLink @@ -170,7 +171,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options return nil; } } else if (options.uri) { - if (options.viewType.value == FVPPlatformVideoViewTypeTextureView) { + if (usesTextureApproach) { player = [[FVPVideoPlayerTextureApproach alloc] initWithURL:[NSURL URLWithString:options.uri] frameUpdater:frameUpdater displayLink:displayLink diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 7f40d4c0b23..91b2056a6b3 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -22,6 +22,10 @@ NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic, nonnull) FlutterEventChannel *eventChannel; +/// The Flutter event sink used to send events to the Flutter engine. +@property(nonatomic, nonnull) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. +@property(nonatomic) CGAffineTransform preferredTransform; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index 96d926e941f..6eb43096bf8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -11,16 +11,18 @@ /// updates frames, and handles display link callbacks. @interface FVPVideoPlayerTextureApproach : FVPVideoPlayer // The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly) CALayer *flutterViewLayer; +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; // The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic) FVPFrameUpdater *frameUpdater; +@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; // The display link that drives frameUpdater. -@property(nonatomic) FVPDisplayLink *displayLink; +@property(nonatomic, nullable) FVPDisplayLink *displayLink; // Whether a new frame needs to be provided to the engine regardless of the current play/pause state // (e.g., after a seek while paused). If YES, the display link should continue to run until the next // frame is successfully provided. @property(nonatomic, assign) BOOL waitingForFrame; +NS_ASSUME_NONNULL_BEGIN + - (instancetype)initWithURL:(NSURL *)url frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink @@ -28,12 +30,14 @@ avFactory:(id)avFactory registrar:(NSObject *)registrar; -- (instancetype)initWithAsset:(AVPlayerItem *)item +- (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory registrar:(NSObject *)registrar; +NS_ASSUME_NONNULL_END + // Tells the player to run its frame updater until it receives a frame, regardless of the // play/pause state. - (void)expectFrame; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index c700c57203b..2a9c6285edb 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -33,4 +33,4 @@ - (instancetype)initWithMessenger:(NSObject *)messenger - (NSObject *)createArgsCodec { return FVPGetMessagesCodec(); } -@end \ No newline at end of file +@end From bbf2efaac44f32699fd39024baa30781b745aecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 13:04:58 +0100 Subject: [PATCH 055/167] Split code into fiels and fix implementations to separate texture approach from platform view approach --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 4 ++-- .../include/video_player_avfoundation/FVPVideoPlayer.h | 4 ---- .../video_player_avfoundation/FVPVideoPlayerTextureApproach.h | 2 +- .../video_player_avfoundation_ios/FVPNativeVideoViewFactory.m | 1 + 4 files changed, 4 insertions(+), 7 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 6df570d388e..0f7ce2fc430 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 @@ -91,8 +91,8 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { // FIXME Rename textureId to playerId, in all other places as well. int64_t textureId; - if (frameUpdater) { - textureId = [self.registry registerTexture:player]; + if (frameUpdater && [player isKindOfClass:[FVPVideoPlayerTextureApproach class]]) { + textureId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; frameUpdater.textureId = textureId; } else { // FIXME Possibly start with a predefined prefix and then increment it to avoid diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 91b2056a6b3..4545aa96f69 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -22,8 +22,6 @@ NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic, nonnull) FlutterEventChannel *eventChannel; -/// The Flutter event sink used to send events to the Flutter engine. -@property(nonatomic, nonnull) FlutterEventSink eventSink; /// The preferred transform for the video. It can be used to handle the rotation of the video. @property(nonatomic) CGAffineTransform preferredTransform; /// Indicates whether the video player has been disposed. @@ -33,8 +31,6 @@ NS_ASSUME_NONNULL_BEGIN /// The current playback position of the video, in milliseconds. @property(readonly, nonatomic) int64_t position; -NS_ASSUME_NONNULL_BEGIN - /// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, /// HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index 6eb43096bf8..e9b11f0e367 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -9,7 +9,7 @@ /// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of /// displaying the video in the app. It manages the CALayer associated with the Flutter view, /// updates frames, and handles display link callbacks. -@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer +@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer // The CALayer associated with the Flutter view this plugin is associated with, if any. @property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; // The updater that drives callbacks to the engine to indicate that a new frame is ready. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 2a9c6285edb..fe60b2e0f9b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" #import "./include/FVPNativeVideoView.h" #import "./include/FVPNativeVideoViewFactory.h" From 39dd125640a09a622470e064f22b78d6e40bffc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 13:23:36 +0100 Subject: [PATCH 056/167] Adjust tests to use FVPVideoPlayerTextureApproach --- .../darwin/RunnerTests/VideoPlayerTests.m | 25 +++++++---- .../FVPVideoPlayer.m | 41 +++++++++++++++---- 2 files changed, 50 insertions(+), 16 deletions(-) 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 2ef43ad0be7..10675f88218 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -276,7 +276,8 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { // Seeking to a new position should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayerTextureApproach *player = + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -342,7 +343,8 @@ - (void)testInitStartsDisplayLinkTemporarily { .ignoringNonObjectArgs() .andReturn(fakeBufferRef); // Simulate a callback from the engine to request a new frame. - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayerTextureApproach *player = + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; [player copyPixelBuffer]; // Since a frame was found, and the video is paused, the display link should be paused again. OCMVerify([mockDisplayLink setRunning:NO]); @@ -394,7 +396,8 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { [self waitForExpectationsWithTimeout:30.0 handler:nil]; OCMVerify([mockDisplayLink setRunning:YES]); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayerTextureApproach *player = + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -814,7 +817,8 @@ - (void)testHotReloadDoesNotCrash { XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayerTextureApproach *player = + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; XCTAssertNotNil(player); weakPlayer = player; @@ -882,11 +886,14 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { [videoPlayerPlugin initialize:&error]; - FVPCreationOptions *create = [FVPCreationOptions makeWithAsset:nil - uri:@"" - packageName:nil - formatHint:nil - httpHeaders:@{}]; + FVPCreationOptions *create = + [FVPCreationOptions makeWithAsset:nil + uri:@"" + packageName:nil + formatHint:nil + httpHeaders:@{} + viewType:[[FVPPlatformVideoViewTypeBox alloc] + initWithValue:FVPPlatformVideoViewTypePlatformView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; XCTAssertNotNil(player); diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index fb020cda3db..16517c0b8db 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -252,13 +252,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]; break; case AVPlayerItemStatusUnknown: break; @@ -310,6 +304,32 @@ - (void)updatePlayingState { } } +- (void)sendFailedToLoadVideoEvent { + if (_eventSink == nil) { + return; + } + // 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) { + [details addObject:detail]; + } + }; + NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; + add(error.localizedDescription); + add(error.localizedFailureReason); + add(underlyingError.localizedDescription); + add(underlyingError.localizedFailureReason); + NSString *message = [details.array componentsJoinedByString:@": "]; + _eventSink([FlutterError errorWithCode:@"VideoError" message:message details:nil]); +} + - (void)setupEventSinkIfReadyToPlay { if (_eventSink && !_isInitialized) { AVPlayerItem *currentItem = self.player.currentItem; @@ -443,6 +463,13 @@ - (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) + // 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]; + return nil; + } [self setupEventSinkIfReadyToPlay]; return nil; } From ad38f1c7201edebfcc9dcb0c90bef405aab7a5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 15:27:35 +0100 Subject: [PATCH 057/167] Make video_player platform interface backwards compatible --- .../example/lib/mini_controller.dart | 16 +++-- .../lib/src/avfoundation_video_player.dart | 23 ++++++-- .../lib/video_player_platform_interface.dart | 58 +++++++++++++------ 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index e00929610f8..335836872c8 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -231,27 +231,30 @@ class MiniController extends ValueNotifier { sourceType: DataSourceType.asset, asset: dataSource, package: package, + viewType: viewType, ); case DataSourceType.network: dataSourceDescription = DataSource( sourceType: DataSourceType.network, uri: dataSource, + viewType: viewType, ); case DataSourceType.file: dataSourceDescription = DataSource( sourceType: DataSourceType.file, uri: dataSource, + viewType: viewType, ); case DataSourceType.contentUri: dataSourceDescription = DataSource( sourceType: DataSourceType.contentUri, uri: dataSource, + viewType: viewType, ); } - _textureId = - (await _platform.create(dataSourceDescription, viewType: viewType)) ?? - kUninitializedTextureId; + _textureId = (await _platform.create(dataSourceDescription)) ?? + kUninitializedTextureId; _creatingCompleter!.complete(null); final Completer initializingCompleter = Completer(); @@ -433,7 +436,12 @@ class _VideoPlayerState extends State { Widget build(BuildContext context) { return _textureId == MiniController.kUninitializedTextureId ? Container() - : _platform.buildView(_textureId, widget.controller.viewType); + : _platform.buildViewWithOptions( + VideoViewOptions( + playerId: _textureId, + viewType: widget.controller.viewType, + ), + ); } } diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index ad9672aaf82..79f10c91ce4 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -150,10 +150,25 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Widget buildView(int textureId, VideoViewType viewType) { - return switch (viewType) { - VideoViewType.textureView => Texture(textureId: textureId), - VideoViewType.platformView => _buildPlatformView(textureId), + Widget buildView(int textureId) { + return buildViewWithOptions( + VideoViewOptions( + playerId: textureId, + // Texture view was the only supported view type before + // buildViewWithOptions was introduced. We pass it here to maintain + // backwards compatibility. + viewType: VideoViewType.textureView, + ), + ); + } + + @override + Widget buildViewWithOptions(VideoViewOptions options) { + final int playerId = options.playerId; + + return switch (options.viewType) { + VideoViewType.textureView => Texture(textureId: playerId), + VideoViewType.platformView => _buildPlatformView(playerId), }; } diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 54325a2598a..52a1c444de7 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -48,13 +48,8 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('dispose() has not been implemented.'); } - /// Creates an instance of a video player with and returns its textureId. - /// The [viewType] parameter specifies the type of view to be used for the - /// video player. - Future create( - DataSource dataSource, { - VideoViewType viewType = VideoViewType.textureView, - }) { + /// Creates an instance of a video player and returns its textureId. + Future create(DataSource dataSource) { throw UnimplementedError('create() has not been implemented.'); } @@ -98,12 +93,17 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('getPosition() has not been implemented.'); } - /// Returns a widget displaying the video with a given textureID, using given - /// viewType. - Widget buildView(int textureId, VideoViewType viewType) { + /// Returns a widget displaying the video with a given textureID. + @Deprecated('Use buildViewWithOptions() instead.') + Widget buildView(int textureId) { throw UnimplementedError('buildView() has not been implemented.'); } + /// Returns a widget displaying the video based on given options. + Widget buildViewWithOptions(VideoViewOptions options) { + return buildView(options.playerId); + } + /// Sets the audio mode to mix with other sources Future setMixWithOthers(bool mixWithOthers) { throw UnimplementedError('setMixWithOthers() has not been implemented.'); @@ -117,15 +117,6 @@ abstract class VideoPlayerPlatform extends PlatformInterface { class _PlaceholderImplementation extends VideoPlayerPlatform {} -/// Enum representing the type of video view to be used. -enum VideoViewType { - /// Uses a texture view for rendering video. - textureView, - - /// Uses a platform view for rendering video. - platformView, -} - /// Description of the data source used to create an instance of /// the video player. class DataSource { @@ -149,6 +140,7 @@ class DataSource { this.asset, this.package, this.httpHeaders = const {}, + this.viewType = VideoViewType.textureView, }); /// The way in which the video was originally loaded. @@ -178,6 +170,9 @@ class DataSource { /// The package that the asset was loaded from. Only set for /// [DataSourceType.asset] videos. final String? package; + + /// The type of view to be used for displaying the video player. + final VideoViewType viewType; } /// The way in which the video was originally loaded. @@ -213,6 +208,15 @@ enum VideoFormat { other, } +/// Enum representing the type of video view to be used. +enum VideoViewType { + /// Uses a texture view for rendering video. + textureView, + + /// Uses a platform view for rendering video. + platformView, +} + /// Event emitted from the platform implementation. @immutable class VideoEvent { @@ -491,3 +495,19 @@ class VideoPlayerWebOptionsControls { return controlsList.join(' '); } } + +/// [VideoViewOptions] contains configuration options for a video view. +@immutable +class VideoViewOptions { + /// Constructs an instance of [VideoViewOptions]. + const VideoViewOptions({ + required this.playerId, + required this.viewType, + }); + + /// The identifier of the video player. + final int playerId; + + /// The type of the video view. + final VideoViewType viewType; +} From fd64cbec2d68148a0c97b7de6547e74151a8a1ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 15:33:51 +0100 Subject: [PATCH 058/167] Bump iOS package version to 2.7.0 --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 4 ++++ packages/video_player/video_player_avfoundation/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 55d1435a118..7e19c39689a 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.7.0 + +* Adds support for platform views as the optional way of displaying a video. + ## 2.6.4 * Refactors native code structure. diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 233a9b65e86..21f10e6e75f 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.4 +version: 2.7.0 environment: sdk: ^3.3.0 From 5132b9982fcc6e9f25b665fbeb61101eb4908adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 15:40:45 +0100 Subject: [PATCH 059/167] Add viewType parameter to VideoPlayerController and use it to display view --- .../video_player/lib/video_player.dart | 45 +++++++++++++------ .../lib/video_player_platform_interface.dart | 2 +- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index b7ba8340fa6..6e161e80375 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -270,11 +270,13 @@ class VideoPlayerController extends ValueNotifier { /// The name of the asset is given by the [dataSource] argument and must not be /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. - VideoPlayerController.asset(this.dataSource, - {this.package, - Future? closedCaptionFile, - this.videoPlayerOptions}) - : _closedCaptionFileFuture = closedCaptionFile, + VideoPlayerController.asset( + this.dataSource, { + this.package, + Future? closedCaptionFile, + this.videoPlayerOptions, + this.viewType = VideoViewType.textureView, + }) : _closedCaptionFileFuture = closedCaptionFile, dataSourceType = DataSourceType.asset, formatHint = null, httpHeaders = const {}, @@ -296,6 +298,7 @@ class VideoPlayerController extends ValueNotifier { Future? closedCaptionFile, this.videoPlayerOptions, this.httpHeaders = const {}, + this.viewType = VideoViewType.textureView, }) : _closedCaptionFileFuture = closedCaptionFile, dataSourceType = DataSourceType.network, package = null, @@ -316,6 +319,7 @@ class VideoPlayerController extends ValueNotifier { Future? closedCaptionFile, this.videoPlayerOptions, this.httpHeaders = const {}, + this.viewType = VideoViewType.textureView, }) : _closedCaptionFileFuture = closedCaptionFile, dataSource = url.toString(), dataSourceType = DataSourceType.network, @@ -326,11 +330,13 @@ class VideoPlayerController extends ValueNotifier { /// /// This will load the file from a file:// URI constructed from [file]'s path. /// [httpHeaders] option allows to specify HTTP headers, mainly used for hls files like (m3u8). - VideoPlayerController.file(File file, - {Future? closedCaptionFile, - this.videoPlayerOptions, - this.httpHeaders = const {}}) - : _closedCaptionFileFuture = closedCaptionFile, + VideoPlayerController.file( + File file, { + Future? closedCaptionFile, + this.videoPlayerOptions, + this.httpHeaders = const {}, + this.viewType = VideoViewType.textureView, + }) : _closedCaptionFileFuture = closedCaptionFile, dataSource = Uri.file(file.absolute.path).toString(), dataSourceType = DataSourceType.file, package = null, @@ -341,9 +347,12 @@ class VideoPlayerController extends ValueNotifier { /// /// This will load the video from the input content-URI. /// This is supported on Android only. - VideoPlayerController.contentUri(Uri contentUri, - {Future? closedCaptionFile, this.videoPlayerOptions}) - : assert(defaultTargetPlatform == TargetPlatform.android, + VideoPlayerController.contentUri( + Uri contentUri, { + Future? closedCaptionFile, + this.videoPlayerOptions, + this.viewType = VideoViewType.textureView, + }) : assert(defaultTargetPlatform == TargetPlatform.android, 'VideoPlayerController.contentUri is only supported on Android.'), _closedCaptionFileFuture = closedCaptionFile, dataSource = contentUri.toString(), @@ -376,6 +385,9 @@ class VideoPlayerController extends ValueNotifier { /// Only set for [asset] videos. The package that the asset was loaded from. final String? package; + /// The type of view used to display the video. + final VideoViewType viewType; + Future? _closedCaptionFileFuture; ClosedCaptionFile? _closedCaptionFile; Timer? _timer; @@ -877,7 +889,12 @@ class _VideoPlayerState extends State { ? Container() : _VideoPlayerWithRotation( rotation: widget.controller.value.rotationCorrection, - child: _videoPlayerPlatform.buildView(_textureId), + child: _videoPlayerPlatform.buildViewWithOptions( + VideoViewOptions( + playerId: _textureId, + viewType: widget.controller.viewType, + ), + ), ); } } diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 52a1c444de7..66fb1b2aec6 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -208,7 +208,7 @@ enum VideoFormat { other, } -/// Enum representing the type of video view to be used. +/// The type of video view to be used. enum VideoViewType { /// Uses a texture view for rendering video. textureView, From 4df644937187c372633ff9ffa579c643bd65cda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 16:13:55 +0100 Subject: [PATCH 060/167] Improve if statements readability --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 0f7ce2fc430..c6cf14d508b 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 @@ -89,9 +89,11 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { + BOOL usesTextureApproach = + frameUpdater != nil && [player isKindOfClass:[FVPVideoPlayerTextureApproach class]]; // FIXME Rename textureId to playerId, in all other places as well. int64_t textureId; - if (frameUpdater && [player isKindOfClass:[FVPVideoPlayerTextureApproach class]]) { + if (usesTextureApproach) { textureId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; frameUpdater.textureId = textureId; } else { @@ -108,10 +110,9 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater player.eventChannel = eventChannel; self.playersByTextureId[@(textureId)] = player; - if (frameUpdater) { + if (usesTextureApproach) { // Ensure that the first frame is drawn once available, even if the video isn't played, since // the engine is now expecting the texture to be populated. - // We can safely cast to FVPVideoPlayerTextureApproach since frameUpdater is non-nil. [(FVPVideoPlayerTextureApproach *)player expectFrame]; } From a885632f46bc32bfd646b6d313a26d62953a0e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 16:18:59 +0100 Subject: [PATCH 061/167] Rename textureId to playerId in onPlayerSetup --- .../FVPVideoPlayerPlugin.m | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 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 c6cf14d508b..adf710e8f30 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 @@ -91,24 +91,23 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { BOOL usesTextureApproach = frameUpdater != nil && [player isKindOfClass:[FVPVideoPlayerTextureApproach class]]; - // FIXME Rename textureId to playerId, in all other places as well. - int64_t textureId; + int64_t playerId; if (usesTextureApproach) { - textureId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; - frameUpdater.textureId = textureId; + playerId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; + frameUpdater.textureId = playerId; } else { // FIXME Possibly start with a predefined prefix and then increment it to avoid // collisions withtextureId. - textureId = arc4random(); + playerId = arc4random(); } FlutterEventChannel *eventChannel = [FlutterEventChannel - eventChannelWithName:[NSString stringWithFormat:@"flutter.io/videoPlayer/videoEvents%lld", - textureId] + eventChannelWithName:[NSString + stringWithFormat:@"flutter.io/videoPlayer/videoEvents%lld", playerId] binaryMessenger:_messenger]; [eventChannel setStreamHandler:player]; player.eventChannel = eventChannel; - self.playersByTextureId[@(textureId)] = player; + self.playersByTextureId[@(playerId)] = player; if (usesTextureApproach) { // Ensure that the first frame is drawn once available, even if the video isn't played, since @@ -116,7 +115,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater [(FVPVideoPlayerTextureApproach *)player expectFrame]; } - return textureId; + return playerId; } - (void)initialize:(FlutterError *__autoreleasing *)error { From 3cb73896e461ac1775971bd74412ac146cefdcef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 17:21:02 +0100 Subject: [PATCH 062/167] Fix overriding create method from platform interface on iOS --- .../lib/src/avfoundation_video_player.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 79f10c91ce4..406208d503e 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -32,10 +32,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Future create( - DataSource dataSource, { - VideoViewType viewType = VideoViewType.textureView, - }) async { + Future create(DataSource dataSource) async { String? asset; String? packageName; String? uri; @@ -60,7 +57,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { uri: uri, httpHeaders: httpHeaders, formatHint: formatHint, - viewType: _platformVideoViewTypeFromVideoViewType(viewType), + viewType: _platformVideoViewTypeFromVideoViewType(dataSource.viewType), ); return _api.create(options); From 5dc241eaf66707bc7995dc1bac7a7fca9b5a146f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 26 Nov 2024 17:21:36 +0100 Subject: [PATCH 063/167] Start non-texture player ids from a high number to avoid collisions --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 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 adf710e8f30..96299a0c9d9 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 @@ -40,6 +40,10 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr #pragma mark - +/// The next non-texture player ID, initialized to a high number to avoid collisions with +/// texture IDs (which are generated separately). +static int64_t nextNonTexturePlayerId = 1000000; + @interface FVPVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject *registry; @property(readonly, weak, nonatomic) NSObject *messenger; @@ -96,9 +100,9 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater playerId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; frameUpdater.textureId = playerId; } else { - // FIXME Possibly start with a predefined prefix and then increment it to avoid - // collisions withtextureId. - playerId = arc4random(); + @synchronized(self) { + playerId = nextNonTexturePlayerId++; + } } FlutterEventChannel *eventChannel = [FlutterEventChannel From fe61a20c5ae5d085ab55fc95cb5081854949858a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 09:28:14 +0100 Subject: [PATCH 064/167] Update comments --- .../lib/src/avfoundation_video_player.dart | 2 +- .../lib/video_player_platform_interface.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 406208d503e..8f509cdc6e0 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -25,7 +25,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { return _api.initialize(); } - // FIXME Rename textureId to playerId everywhere. + // TODO(FirentisTFW): Rename textureId to playerId everywhere. @override Future dispose(int textureId) { return _api.dispose(textureId); diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 66fb1b2aec6..5b2bb0aed1b 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -101,6 +101,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { /// Returns a widget displaying the video based on given options. Widget buildViewWithOptions(VideoViewOptions options) { + // Default implementation for backwards compatibility. return buildView(options.playerId); } From 9c38562d90dbab1992fc38f1ef38dd5b46851b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 09:28:27 +0100 Subject: [PATCH 065/167] Add viewType to FakeController in tests --- packages/video_player/video_player/test/video_player_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index f6eef244811..c6e6de841ae 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -46,6 +46,9 @@ class FakeController extends ValueNotifier @override Future get position async => value.position; + @override + VideoViewType get viewType => VideoViewType.textureView; + @override Future seekTo(Duration moment) async {} From 6705387557473e13db67e151497a15451838c9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 10:42:11 +0100 Subject: [PATCH 066/167] Use correct view type to create data source in the main package --- packages/video_player/video_player/lib/video_player.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index 6e161e80375..fa1f6bcac65 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -423,6 +423,7 @@ class VideoPlayerController extends ValueNotifier { sourceType: DataSourceType.asset, asset: dataSource, package: package, + viewType: viewType, ); case DataSourceType.network: dataSourceDescription = DataSource( @@ -430,17 +431,20 @@ class VideoPlayerController extends ValueNotifier { uri: dataSource, formatHint: formatHint, httpHeaders: httpHeaders, + viewType: viewType, ); case DataSourceType.file: dataSourceDescription = DataSource( sourceType: DataSourceType.file, uri: dataSource, httpHeaders: httpHeaders, + viewType: viewType, ); case DataSourceType.contentUri: dataSourceDescription = DataSource( sourceType: DataSourceType.contentUri, uri: dataSource, + viewType: viewType, ); } From fe88ebff34300f2817ce57a675e16de7d7a52516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 10:42:38 +0100 Subject: [PATCH 067/167] Add unit tests for passing view type correctly --- .../video_player/test/video_player_test.dart | 10 +++++++++ .../test/avfoundation_video_player_test.dart | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index c6e6de841ae..900d75ddce5 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -475,6 +475,16 @@ void main() { await controller.initialize(); expect(controller.value.hasError, equals(false)); }); + + test('uses passed view type', () async { + final VideoPlayerController controller = VideoPlayerController.file( + File('a.avi'), + viewType: VideoViewType.platformView); + await controller.initialize(); + + expect(fakeVideoPlayerPlatform.dataSources[0].viewType, + VideoViewType.platformView); + }); }); test('contentUri', () async { diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index dac0553fbed..d23c73dd20a 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -188,6 +188,28 @@ void main() { expect(textureId, 3); }); + test('create with texture view', () async { + final int? textureId = await player.create(DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + // Texture view is a default view type. + )); + expect(log.log.last, 'create'); + expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); + expect(textureId, 3); + }); + + test('create with platform view', () async { + final int? textureId = await player.create(DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + viewType: VideoViewType.platformView, + )); + expect(log.log.last, 'create'); + expect(log.creationOptions?.viewType, PlatformVideoViewType.platformView); + expect(textureId, 3); + }); + test('setLooping', () async { await player.setLooping(1, true); expect(log.log.last, 'setLooping'); From 85f088d128a55ad53d2b011a6de99b06b5ff0c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 11:18:25 +0100 Subject: [PATCH 068/167] Throw an assertion if platform view is used on platform different than iOS and Android --- .../video_player/lib/video_player.dart | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index fa1f6bcac65..47c17226e87 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -280,7 +280,9 @@ class VideoPlayerController extends ValueNotifier { dataSourceType = DataSourceType.asset, formatHint = null, httpHeaders = const {}, - super(const VideoPlayerValue(duration: Duration.zero)); + super(const VideoPlayerValue(duration: Duration.zero)) { + _validateConstructorInput(); + } /// Constructs a [VideoPlayerController] playing a network video. /// @@ -302,7 +304,9 @@ class VideoPlayerController extends ValueNotifier { }) : _closedCaptionFileFuture = closedCaptionFile, dataSourceType = DataSourceType.network, package = null, - super(const VideoPlayerValue(duration: Duration.zero)); + super(const VideoPlayerValue(duration: Duration.zero)) { + _validateConstructorInput(); + } /// Constructs a [VideoPlayerController] playing a network video. /// @@ -324,7 +328,9 @@ class VideoPlayerController extends ValueNotifier { dataSource = url.toString(), dataSourceType = DataSourceType.network, package = null, - super(const VideoPlayerValue(duration: Duration.zero)); + super(const VideoPlayerValue(duration: Duration.zero)) { + _validateConstructorInput(); + } /// Constructs a [VideoPlayerController] playing a video from a file. /// @@ -341,7 +347,9 @@ class VideoPlayerController extends ValueNotifier { dataSourceType = DataSourceType.file, package = null, formatHint = null, - super(const VideoPlayerValue(duration: Duration.zero)); + super(const VideoPlayerValue(duration: Duration.zero)) { + _validateConstructorInput(); + } /// Constructs a [VideoPlayerController] playing a video from a contentUri. /// @@ -360,7 +368,9 @@ class VideoPlayerController extends ValueNotifier { package = null, formatHint = null, httpHeaders = const {}, - super(const VideoPlayerValue(duration: Duration.zero)); + super(const VideoPlayerValue(duration: Duration.zero)) { + _validateConstructorInput(); + } /// The URI to the video file. This will be in different formats depending on /// the [DataSourceType] of the original video. @@ -406,6 +416,15 @@ class VideoPlayerController extends ValueNotifier { @visibleForTesting int get textureId => _textureId; + /// Validates the values passed in the constructor. + void _validateConstructorInput() { + assert( + viewType != VideoViewType.platformView || + defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS, + 'VideoViewType.platformView is only supported on Android and iOS.'); + } + /// Attempts to open the given [dataSource] and load metadata about the video. Future initialize() async { final bool allowBackgroundPlayback = From 04d0e8dc44952ac999fec9e131ff4d686167e71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 12:36:34 +0100 Subject: [PATCH 069/167] Adjust example app to allow changing view type on iOS --- .../video_player/example/lib/main.dart | 107 ++++++++++++++++-- .../video_player/lib/video_player.dart | 3 +- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/packages/video_player/video_player/example/lib/main.dart b/packages/video_player/video_player/example/lib/main.dart index 0ce77d603b5..c3aa5fc7649 100644 --- a/packages/video_player/video_player/example/lib/main.dart +++ b/packages/video_player/video_player/example/lib/main.dart @@ -8,6 +8,8 @@ /// video. library; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; @@ -55,18 +57,97 @@ class _App extends StatelessWidget { ), ), body: TabBarView( - children: [ - _BumbleBeeRemoteVideo(), - _ButterFlyAssetVideo(), - _ButterFlyAssetVideoInList(), - ], + children: Platform.isIOS + ? [ + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeRemoteVideo(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _ButterFlyAssetVideo(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _ButterFlyAssetVideoInList(viewType), + ), + ] + // We don't support platform views on other platforms yet. + : const [ + _BumbleBeeRemoteVideo(VideoViewType.textureView), + _ButterFlyAssetVideo(VideoViewType.textureView), + _ButterFlyAssetVideoInList(VideoViewType.textureView), + ], ), ), ); } } +class _ViewTypeTabBar extends StatefulWidget { + const _ViewTypeTabBar({ + required this.builder, + }); + + final Widget Function(VideoViewType) builder; + + @override + State<_ViewTypeTabBar> createState() => _ViewTypeTabBarState(); +} + +class _ViewTypeTabBarState extends State<_ViewTypeTabBar> + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + TabBar( + controller: _tabController, + isScrollable: true, + tabs: const [ + Tab( + icon: Icon(Icons.texture), + text: 'Texture view', + ), + Tab( + icon: Icon(Icons.construction), + text: 'Platform view', + ), + ], + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + widget.builder(VideoViewType.textureView), + widget.builder(VideoViewType.platformView), + ], + ), + ), + ], + ); + } +} + class _ButterFlyAssetVideoInList extends StatelessWidget { + const _ButterFlyAssetVideoInList(this.viewType); + + final VideoViewType viewType; + @override Widget build(BuildContext context) { return ListView( @@ -90,7 +171,7 @@ class _ButterFlyAssetVideoInList extends StatelessWidget { alignment: FractionalOffset.bottomRight + const FractionalOffset(-0.1, -0.1), children: [ - _ButterFlyAssetVideo(), + _ButterFlyAssetVideo(viewType), Image.asset('assets/flutter-mark-square-64.png'), ]), ], @@ -150,6 +231,10 @@ class _ExampleCard extends StatelessWidget { } class _ButterFlyAssetVideo extends StatefulWidget { + const _ButterFlyAssetVideo(this.viewType); + + final VideoViewType viewType; + @override _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState(); } @@ -160,7 +245,10 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { @override void initState() { super.initState(); - _controller = VideoPlayerController.asset('assets/Butterfly-209.mp4'); + _controller = VideoPlayerController.asset( + 'assets/Butterfly-209.mp4', + viewType: widget.viewType, + ); _controller.addListener(() { setState(() {}); @@ -206,6 +294,10 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { } class _BumbleBeeRemoteVideo extends StatefulWidget { + const _BumbleBeeRemoteVideo(this.viewType); + + final VideoViewType viewType; + @override _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState(); } @@ -228,6 +320,7 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'), closedCaptionFile: _loadCaptions(), videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), + viewType: widget.viewType, ); _controller.addListener(() { diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index 47c17226e87..531f193b219 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -20,7 +20,8 @@ export 'package:video_player_platform_interface/video_player_platform_interface. VideoFormat, VideoPlayerOptions, VideoPlayerWebOptions, - VideoPlayerWebOptionsControls; + VideoPlayerWebOptionsControls, + VideoViewType; export 'src/closed_caption_file.dart'; From 07874ee44dd13cfca453d4a19d438033e2984b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 13:59:39 +0100 Subject: [PATCH 070/167] Add missing doc comments --- .../video_player_avfoundation/FVPVideoPlayer.h | 11 +++++------ .../FVPVideoPlayerTextureApproach.h | 4 ++++ .../include/FVPNativeVideoViewFactory.h | 4 ++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 4545aa96f69..22f48eb7456 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -31,21 +31,20 @@ NS_ASSUME_NONNULL_BEGIN /// The current playback position of the video, in milliseconds. @property(readonly, nonatomic) int64_t position; -/// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, -/// HTTP headers, AV factory, and registrar. +/// Initializes a new instance of FVPVideoPlayer with the given URL, HTTP headers, AV factory, and +/// registrar. - (instancetype)initWithURL:(NSURL *)url httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display -/// link, AV factory, and registrar. +/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, AV factory, and +/// registrar. - (instancetype)initWithPlayerItem:(AVPlayerItem *)item avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, -/// AV factory, and registrar. +/// Initializes a new instance of FVPVideoPlayer with the given asset, AV factory, and registrar. - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index e9b11f0e367..1ecb2b0d7b2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN +/// Initializes a new instance of FVPVideoPlayerTextureApproach with the given URL, frame updater, +/// display link, HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink @@ -30,6 +32,8 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; +/// Initializes a new instance of FVPVideoPlayerTextureApproach with the given asset, frame updater, +/// display link, AV factory, and registrar. - (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h index fe04fd2967f..ac0a94a40c2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h @@ -6,7 +6,11 @@ #import "FVPVideoPlayer.h" +/// A factory class responsible for creating native video views that can be embedded in a +/// Flutter app. @interface FVPNativeVideoViewFactory : NSObject +/// Initializes a new instance of FVPNativeVideoViewFactory with the given messenger and +/// playersByTextureId dictionary which stores the video players associated with the texture IDs. - (instancetype)initWithMessenger:(NSObject *)messenger playersByTextureId: (NSMutableDictionary *)playersByTextureId; From eba2c3666bd5d4e23c87e63163289aeed5e680b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 27 Nov 2024 14:00:05 +0100 Subject: [PATCH 071/167] Remove placeholder files which are not needed anymore --- .../Sources/video_player_avfoundation_ios/include/.gitkeep | 0 .../video_player_avfoundation_ios/include/FVPEmpty.h | 6 ------ 2 files changed, 6 deletions(-) delete mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep delete mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h deleted file mode 100644 index c7b344f7299..00000000000 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h +++ /dev/null @@ -1,6 +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. - -// Empty file to perserve include directory in pub-cache. See -// https://github.com/flutter/flutter/issues/148002 for more information. From c2defa6209ab71c471a4d150ddee63d80b0e4fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 16:50:10 +0100 Subject: [PATCH 072/167] Clean up player's properties after rebase --- .../darwin/RunnerTests/VideoPlayerTests.m | 4 ++- .../FVPVideoPlayer.m | 28 ------------------ .../FVPVideoPlayerPlugin.m | 2 +- .../FVPVideoPlayerTextureApproach.m | 19 ++++++++++-- .../FVPVideoPlayer.h | 26 +++++++++++++---- .../FVPVideoPlayerTextureApproach.h | 23 ++++----------- .../FVPVideoPlayerTextureApproach_Test.h | 29 +++++++++++++++++++ .../FVPVideoPlayer_Test.h | 19 +----------- 8 files changed, 77 insertions(+), 73 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h 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 10675f88218..038797116c9 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -9,6 +9,7 @@ #import #import #import +#import // TODO(stuartmorgan): Convert to using mock registrars instead. NSObject *GetPluginRegistry(void) { @@ -185,7 +186,8 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayerTextureApproach *player = + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; XCTAssertNotNil(player); XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present."); diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 16517c0b8db..4055e4e87dc 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -14,34 +14,6 @@ static void *playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext; static void *rateContext = &rateContext; -@interface FVPVideoPlayer () -/// The AVPlayerItemVideoOutput associated with this video player. -@property(readonly, nonatomic, nonnull) AVPlayerItemVideoOutput *videoOutput; -/// The plugin registrar, to obtain view information from. -@property(nonatomic, readonly) NSObject *registrar; -/// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; -/// The Flutter event sink used to send events to the Flutter engine. -@property(nonatomic, nonnull) FlutterEventSink eventSink; -/// The preferred transform for the video. It can be used to handle the rotation of the video. -@property(nonatomic) CGAffineTransform preferredTransform; -/// Indicates whether the video player is currently playing. -@property(nonatomic, readonly) BOOL isPlaying; -/// Indicates whether the video player has been initialized. -@property(nonatomic, readonly) BOOL isInitialized; -/// The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; -/// The display link that drives frameUpdater. -@property(nonatomic, nullable) FVPDisplayLink *displayLink; -/// Whether a new frame needs to be provided to the engine regardless of the current play/pause -/// state (e.g., after a seek while paused). If YES, the display link should continue to run until -/// the next frame is successfully provided. -@property(nonatomic, assign) BOOL waitingForFrame; - -/// Updates the playing state of the video player. -- (void)updatePlayingState; -@end - @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory 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 96299a0c9d9..5ed5218791b 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 @@ -11,7 +11,7 @@ #import "./include/video_player_avfoundation/FVPFrameUpdater.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" -#import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" +#import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" // Relative path is needed for messages.g.h. See: // https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m index c94cb556edb..d9d96dcb095 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m @@ -2,7 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FVPVideoPlayerTextureApproach.h" +#import "FVPVideoPlayerTextureApproach_Test.h" + +@interface FVPVideoPlayerTextureApproach () +// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; +// The updater that drives callbacks to the engine to indicate that a new frame is ready. +@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; +// The display link that drives frameUpdater. +@property(nonatomic, nullable) FVPDisplayLink *displayLink; +// Whether a new frame needs to be provided to the engine regardless of the current play/pause state +// (e.g., after a seek while paused). If YES, the display link should continue to run until the next +// frame is successfully provided. +@property(nonatomic, assign) BOOL waitingForFrame; +@end @implementation FVPVideoPlayerTextureApproach - (instancetype)initWithAsset:(NSString *)asset @@ -62,7 +75,7 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item // 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. - self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; + _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; [self.flutterViewLayer addSublayer:self.playerLayer]; } return self; @@ -107,7 +120,7 @@ - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHan - (void)expectFrame { self.waitingForFrame = YES; - self.displayLink.running = YES; + _displayLink.running = YES; } - (CVPixelBufferRef)copyPixelBuffer { diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 22f48eb7456..cd025140c51 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -22,8 +22,8 @@ NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic, nonnull) FlutterEventChannel *eventChannel; -/// The preferred transform for the video. It can be used to handle the rotation of the video. -@property(nonatomic) CGAffineTransform preferredTransform; +/// The AVPlayer instance used for video playback. +@property(readonly, nonatomic) AVPlayer *player; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @@ -72,10 +72,26 @@ NS_ASSUME_NONNULL_BEGIN /// Seeks to the specified location in the video and calls the completion handler when done, if one /// is supplied. - (void)seekTo:(int64_t)location completionHandler:(void (^_Nullable)(BOOL))completionHandler; +@end + +@interface FVPVideoPlayer () +/// The AVPlayerItemVideoOutput associated with this video player. +@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; +/// The plugin registrar, to obtain view information from. +@property(nonatomic, readonly) NSObject *registrar; +/// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; +/// The Flutter event sink used to send events to the Flutter engine. +@property(nonatomic) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. +@property(nonatomic) CGAffineTransform preferredTransform; +/// Indicates whether the video player is currently playing. +@property(nonatomic, readonly) BOOL isPlaying; +/// Indicates whether the video player has been initialized. +@property(nonatomic, readonly) BOOL isInitialized; -/// Tells the player to run its frame updater until it receives a frame, regardless of the -/// play/pause state. -- (void)expectFrame; +/// Updates the playing state of the video player. +- (void)updatePlayingState; @end NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index 1ecb2b0d7b2..c1f492a13ae 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -4,25 +4,14 @@ #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" -#import "FVPVideoPlayer.h" +#import "FVPVideoPlayer_Test.h" + +NS_ASSUME_NONNULL_BEGIN /// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of /// displaying the video in the app. It manages the CALayer associated with the Flutter view, /// updates frames, and handles display link callbacks. -@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer -// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; -// The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; -// The display link that drives frameUpdater. -@property(nonatomic, nullable) FVPDisplayLink *displayLink; -// Whether a new frame needs to be provided to the engine regardless of the current play/pause state -// (e.g., after a seek while paused). If YES, the display link should continue to run until the next -// frame is successfully provided. -@property(nonatomic, assign) BOOL waitingForFrame; - -NS_ASSUME_NONNULL_BEGIN - +@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer /// Initializes a new instance of FVPVideoPlayerTextureApproach with the given URL, frame updater, /// display link, HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url @@ -40,9 +29,9 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; -NS_ASSUME_NONNULL_END - // Tells the player to run its frame updater until it receives a frame, regardless of the // play/pause state. - (void)expectFrame; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h new file mode 100644 index 00000000000..c3906cf2e46 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h @@ -0,0 +1,29 @@ +// 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. + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import "FVPVideoPlayerTextureApproach.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FVPVideoPlayerTextureApproach () +/// The AVPlayerLayer used to display the video content. +/// 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; + +/// Called when the texture is unregistered. +/// This method is used to clean up resources associated with the texture. +- (void)onTextureUnregistered:(nullable NSObject *)texture; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h index 4d6717b76d2..3ab7102c21b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h @@ -10,22 +10,5 @@ #import "FVPVideoPlayer.h" -NS_ASSUME_NONNULL_BEGIN - -@interface FVPVideoPlayer () -/// The AVPlayer instance used for video playback. -@property(readonly, nonatomic) AVPlayer *player; -/// The AVPlayerLayer used to display the video content. -/// 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; - -/// Called when the texture is unregistered. -/// This method is used to clean up resources associated with the texture. -- (void)onTextureUnregistered:(nullable NSObject *)texture; +@interface FVPVideoPlayer () @end - -NS_ASSUME_NONNULL_END From 508a21259760ef9d7e08586f8db983da0c30d769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 4 Dec 2024 17:07:44 +0100 Subject: [PATCH 073/167] Remove code related to platform view from the app facing package --- .../video_player/example/lib/main.dart | 107 ++---------------- .../video_player/lib/video_player.dart | 81 ++++--------- .../video_player/test/video_player_test.dart | 13 --- 3 files changed, 27 insertions(+), 174 deletions(-) diff --git a/packages/video_player/video_player/example/lib/main.dart b/packages/video_player/video_player/example/lib/main.dart index c3aa5fc7649..0ce77d603b5 100644 --- a/packages/video_player/video_player/example/lib/main.dart +++ b/packages/video_player/video_player/example/lib/main.dart @@ -8,8 +8,6 @@ /// video. library; -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; @@ -57,97 +55,18 @@ class _App extends StatelessWidget { ), ), body: TabBarView( - children: Platform.isIOS - ? [ - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _BumbleBeeRemoteVideo(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _ButterFlyAssetVideo(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _ButterFlyAssetVideoInList(viewType), - ), - ] - // We don't support platform views on other platforms yet. - : const [ - _BumbleBeeRemoteVideo(VideoViewType.textureView), - _ButterFlyAssetVideo(VideoViewType.textureView), - _ButterFlyAssetVideoInList(VideoViewType.textureView), - ], - ), - ), - ); - } -} - -class _ViewTypeTabBar extends StatefulWidget { - const _ViewTypeTabBar({ - required this.builder, - }); - - final Widget Function(VideoViewType) builder; - - @override - State<_ViewTypeTabBar> createState() => _ViewTypeTabBarState(); -} - -class _ViewTypeTabBarState extends State<_ViewTypeTabBar> - with SingleTickerProviderStateMixin { - late final TabController _tabController; - - @override - void initState() { - super.initState(); - _tabController = TabController(length: 2, vsync: this); - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Column( - children: [ - TabBar( - controller: _tabController, - isScrollable: true, - tabs: const [ - Tab( - icon: Icon(Icons.texture), - text: 'Texture view', - ), - Tab( - icon: Icon(Icons.construction), - text: 'Platform view', - ), + children: [ + _BumbleBeeRemoteVideo(), + _ButterFlyAssetVideo(), + _ButterFlyAssetVideoInList(), ], ), - Expanded( - child: TabBarView( - controller: _tabController, - children: [ - widget.builder(VideoViewType.textureView), - widget.builder(VideoViewType.platformView), - ], - ), - ), - ], + ), ); } } class _ButterFlyAssetVideoInList extends StatelessWidget { - const _ButterFlyAssetVideoInList(this.viewType); - - final VideoViewType viewType; - @override Widget build(BuildContext context) { return ListView( @@ -171,7 +90,7 @@ class _ButterFlyAssetVideoInList extends StatelessWidget { alignment: FractionalOffset.bottomRight + const FractionalOffset(-0.1, -0.1), children: [ - _ButterFlyAssetVideo(viewType), + _ButterFlyAssetVideo(), Image.asset('assets/flutter-mark-square-64.png'), ]), ], @@ -231,10 +150,6 @@ class _ExampleCard extends StatelessWidget { } class _ButterFlyAssetVideo extends StatefulWidget { - const _ButterFlyAssetVideo(this.viewType); - - final VideoViewType viewType; - @override _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState(); } @@ -245,10 +160,7 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { @override void initState() { super.initState(); - _controller = VideoPlayerController.asset( - 'assets/Butterfly-209.mp4', - viewType: widget.viewType, - ); + _controller = VideoPlayerController.asset('assets/Butterfly-209.mp4'); _controller.addListener(() { setState(() {}); @@ -294,10 +206,6 @@ class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> { } class _BumbleBeeRemoteVideo extends StatefulWidget { - const _BumbleBeeRemoteVideo(this.viewType); - - final VideoViewType viewType; - @override _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState(); } @@ -320,7 +228,6 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'), closedCaptionFile: _loadCaptions(), videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), - viewType: widget.viewType, ); _controller.addListener(() { diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index 531f193b219..b7ba8340fa6 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -20,8 +20,7 @@ export 'package:video_player_platform_interface/video_player_platform_interface. VideoFormat, VideoPlayerOptions, VideoPlayerWebOptions, - VideoPlayerWebOptionsControls, - VideoViewType; + VideoPlayerWebOptionsControls; export 'src/closed_caption_file.dart'; @@ -271,19 +270,15 @@ class VideoPlayerController extends ValueNotifier { /// The name of the asset is given by the [dataSource] argument and must not be /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. - VideoPlayerController.asset( - this.dataSource, { - this.package, - Future? closedCaptionFile, - this.videoPlayerOptions, - this.viewType = VideoViewType.textureView, - }) : _closedCaptionFileFuture = closedCaptionFile, + VideoPlayerController.asset(this.dataSource, + {this.package, + Future? closedCaptionFile, + this.videoPlayerOptions}) + : _closedCaptionFileFuture = closedCaptionFile, dataSourceType = DataSourceType.asset, formatHint = null, httpHeaders = const {}, - super(const VideoPlayerValue(duration: Duration.zero)) { - _validateConstructorInput(); - } + super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [VideoPlayerController] playing a network video. /// @@ -301,13 +296,10 @@ class VideoPlayerController extends ValueNotifier { Future? closedCaptionFile, this.videoPlayerOptions, this.httpHeaders = const {}, - this.viewType = VideoViewType.textureView, }) : _closedCaptionFileFuture = closedCaptionFile, dataSourceType = DataSourceType.network, package = null, - super(const VideoPlayerValue(duration: Duration.zero)) { - _validateConstructorInput(); - } + super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [VideoPlayerController] playing a network video. /// @@ -324,44 +316,34 @@ class VideoPlayerController extends ValueNotifier { Future? closedCaptionFile, this.videoPlayerOptions, this.httpHeaders = const {}, - this.viewType = VideoViewType.textureView, }) : _closedCaptionFileFuture = closedCaptionFile, dataSource = url.toString(), dataSourceType = DataSourceType.network, package = null, - super(const VideoPlayerValue(duration: Duration.zero)) { - _validateConstructorInput(); - } + super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [VideoPlayerController] playing a video from a file. /// /// This will load the file from a file:// URI constructed from [file]'s path. /// [httpHeaders] option allows to specify HTTP headers, mainly used for hls files like (m3u8). - VideoPlayerController.file( - File file, { - Future? closedCaptionFile, - this.videoPlayerOptions, - this.httpHeaders = const {}, - this.viewType = VideoViewType.textureView, - }) : _closedCaptionFileFuture = closedCaptionFile, + VideoPlayerController.file(File file, + {Future? closedCaptionFile, + this.videoPlayerOptions, + this.httpHeaders = const {}}) + : _closedCaptionFileFuture = closedCaptionFile, dataSource = Uri.file(file.absolute.path).toString(), dataSourceType = DataSourceType.file, package = null, formatHint = null, - super(const VideoPlayerValue(duration: Duration.zero)) { - _validateConstructorInput(); - } + super(const VideoPlayerValue(duration: Duration.zero)); /// Constructs a [VideoPlayerController] playing a video from a contentUri. /// /// This will load the video from the input content-URI. /// This is supported on Android only. - VideoPlayerController.contentUri( - Uri contentUri, { - Future? closedCaptionFile, - this.videoPlayerOptions, - this.viewType = VideoViewType.textureView, - }) : assert(defaultTargetPlatform == TargetPlatform.android, + VideoPlayerController.contentUri(Uri contentUri, + {Future? closedCaptionFile, this.videoPlayerOptions}) + : assert(defaultTargetPlatform == TargetPlatform.android, 'VideoPlayerController.contentUri is only supported on Android.'), _closedCaptionFileFuture = closedCaptionFile, dataSource = contentUri.toString(), @@ -369,9 +351,7 @@ class VideoPlayerController extends ValueNotifier { package = null, formatHint = null, httpHeaders = const {}, - super(const VideoPlayerValue(duration: Duration.zero)) { - _validateConstructorInput(); - } + super(const VideoPlayerValue(duration: Duration.zero)); /// The URI to the video file. This will be in different formats depending on /// the [DataSourceType] of the original video. @@ -396,9 +376,6 @@ class VideoPlayerController extends ValueNotifier { /// Only set for [asset] videos. The package that the asset was loaded from. final String? package; - /// The type of view used to display the video. - final VideoViewType viewType; - Future? _closedCaptionFileFuture; ClosedCaptionFile? _closedCaptionFile; Timer? _timer; @@ -417,15 +394,6 @@ class VideoPlayerController extends ValueNotifier { @visibleForTesting int get textureId => _textureId; - /// Validates the values passed in the constructor. - void _validateConstructorInput() { - assert( - viewType != VideoViewType.platformView || - defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS, - 'VideoViewType.platformView is only supported on Android and iOS.'); - } - /// Attempts to open the given [dataSource] and load metadata about the video. Future initialize() async { final bool allowBackgroundPlayback = @@ -443,7 +411,6 @@ class VideoPlayerController extends ValueNotifier { sourceType: DataSourceType.asset, asset: dataSource, package: package, - viewType: viewType, ); case DataSourceType.network: dataSourceDescription = DataSource( @@ -451,20 +418,17 @@ class VideoPlayerController extends ValueNotifier { uri: dataSource, formatHint: formatHint, httpHeaders: httpHeaders, - viewType: viewType, ); case DataSourceType.file: dataSourceDescription = DataSource( sourceType: DataSourceType.file, uri: dataSource, httpHeaders: httpHeaders, - viewType: viewType, ); case DataSourceType.contentUri: dataSourceDescription = DataSource( sourceType: DataSourceType.contentUri, uri: dataSource, - viewType: viewType, ); } @@ -913,12 +877,7 @@ class _VideoPlayerState extends State { ? Container() : _VideoPlayerWithRotation( rotation: widget.controller.value.rotationCorrection, - child: _videoPlayerPlatform.buildViewWithOptions( - VideoViewOptions( - playerId: _textureId, - viewType: widget.controller.viewType, - ), - ), + child: _videoPlayerPlatform.buildView(_textureId), ); } } diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index 900d75ddce5..f6eef244811 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -46,9 +46,6 @@ class FakeController extends ValueNotifier @override Future get position async => value.position; - @override - VideoViewType get viewType => VideoViewType.textureView; - @override Future seekTo(Duration moment) async {} @@ -475,16 +472,6 @@ void main() { await controller.initialize(); expect(controller.value.hasError, equals(false)); }); - - test('uses passed view type', () async { - final VideoPlayerController controller = VideoPlayerController.file( - File('a.avi'), - viewType: VideoViewType.platformView); - await controller.initialize(); - - expect(fakeVideoPlayerPlatform.dataSources[0].viewType, - VideoViewType.platformView); - }); }); test('contentUri', () async { From 1ee5082f33a2a52cebd82c271efc0c120c2bbba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 11:14:29 +0100 Subject: [PATCH 074/167] Adjust interfaces after merge --- .../FVPVideoPlayer.h | 26 ++++++++++++++++--- .../FVPVideoPlayerTextureApproach.h | 2 +- .../FVPVideoPlayerTextureApproach_Test.h | 2 +- .../FVPVideoPlayer_Test.h | 15 +---------- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index e87754a1ba1..acb73fbe800 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -22,6 +22,8 @@ NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; +/// The AVPlayer instance used for video playback. +@property(readonly, nonatomic) AVPlayer *player; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @@ -71,10 +73,26 @@ NS_ASSUME_NONNULL_BEGIN /// Seeks to the specified location in the video and calls the completion handler when done, if one /// is supplied. - (void)seekTo:(int64_t)location completionHandler:(void (^_Nullable)(BOOL))completionHandler; +@end -/// Tells the player to run its frame updater until it receives a frame, regardless of the -/// play/pause state. -- (void)expectFrame; +@interface FVPVideoPlayer () +/// The AVPlayerItemVideoOutput associated with this video player. +@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; +/// The plugin registrar, to obtain view information from. +@property(nonatomic, readonly) NSObject *registrar; +/// The CALayer associated with the Flutter view this plugin is associated with, if any. +@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; +/// The Flutter event sink used to send events to the Flutter engine. +@property(nonatomic) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. +@property(nonatomic) CGAffineTransform preferredTransform; +/// Indicates whether the video player is currently playing. +@property(nonatomic, readonly) BOOL isPlaying; +/// Indicates whether the video player has been initialized. +@property(nonatomic, readonly) BOOL isInitialized; + +/// Updates the playing state of the video player. +- (void)updatePlayingState; @end -NS_ASSUME_NONNULL_END +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index c1f492a13ae..7a887a16cb4 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN /// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of /// displaying the video in the app. It manages the CALayer associated with the Flutter view, /// updates frames, and handles display link callbacks. -@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer +@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer /// Initializes a new instance of FVPVideoPlayerTextureApproach with the given URL, frame updater, /// display link, HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h index c3906cf2e46..a1f59e7c264 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h @@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface FVPVideoPlayerTextureApproach () +@interface FVPVideoPlayerTextureApproach () /// The AVPlayerLayer used to display the video content. /// 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 diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h index d51d7a1a1e0..2f2ad85e989 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h @@ -12,20 +12,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface FVPVideoPlayer () -/// The AVPlayer instance used for video playback. -@property(readonly, nonatomic) AVPlayer *player; -/// The AVPlayerLayer used to display the video content. -/// 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; - -/// Called when the texture is unregistered. -/// This method is used to clean up resources associated with the texture. -- (void)onTextureUnregistered:(nullable NSObject *)texture; +@interface FVPVideoPlayer () @end NS_ASSUME_NONNULL_END From d9bb76af0d6aef47e76ebdab03740be2b55521ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 11:25:40 +0100 Subject: [PATCH 075/167] Replace hyphens with asterisks in Changelog --- .../video_player_avfoundation/CHANGELOG.md | 118 +++++++++--------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index c028ae675ec..7e19c39689a 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,176 +1,176 @@ ## 2.7.0 -- Adds support for platform views as the optional way of displaying a video. +* Adds support for platform views as the optional way of displaying a video. ## 2.6.4 -- Refactors native code structure. +* Refactors native code structure. ## 2.6.3 -- Fixes VideoPlayerController.initialize() future never resolving with invalid video file. -- Adds more details to the error message returned by VideoPlayerController.initialize(). +* Fixes VideoPlayerController.initialize() future never resolving with invalid video file. +* Adds more details to the error message returned by VideoPlayerController.initialize(). ## 2.6.2 -- Updates Pigeon for non-nullable collection type support. -- Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates Pigeon for non-nullable collection type support. +* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. ## 2.6.1 -- Adds files to make include directory permanent. +* Adds files to make include directory permanent. ## 2.6.0 -- Adds Swift Package Manager compatibility. +* Adds Swift Package Manager compatibility. ## 2.5.7 -- Adds frame availability checks on iOS. -- Simplifies internal platform channel interfaces. -- Updates minimum iOS version to 12.0 and minimum Flutter version to 3.16.6. +* Adds frame availability checks on iOS. +* Simplifies internal platform channel interfaces. +* Updates minimum iOS version to 12.0 and minimum Flutter version to 3.16.6. ## 2.5.6 -- Adds privacy manifest. +* Adds privacy manifest. ## 2.5.5 -- Fixes display of initial frame when paused. +* Fixes display of initial frame when paused. ## 2.5.4 -- Fixes new lint warnings. +* Fixes new lint warnings. ## 2.5.3 -- Publishes an instance of the plugin to the registrar on macOS, as on iOS. +* Publishes an instance of the plugin to the registrar on macOS, as on iOS. ## 2.5.2 -- Fixes flickering and seek-while-paused on macOS. +* Fixes flickering and seek-while-paused on macOS. ## 2.5.1 -- Updates to Pigeon 13. +* Updates to Pigeon 13. ## 2.5.0 -- Adds support for macOS. +* Adds support for macOS. ## 2.4.11 -- Updates Pigeon. -- Changes Objective-C class prefixes to avoid future collisions. +* Updates Pigeon. +* Changes Objective-C class prefixes to avoid future collisions. ## 2.4.10 -- Adds pub topics to package metadata. -- Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. ## 2.4.9 -- Fixes the iOS crash when using multiple players on the same screen. +* Fixes the iOS crash when using multiple players on the same screen. See: https://github.com/flutter/flutter/issues/124937 ## 2.4.8 -- Fixes missing `isPlaybackLikelyToKeepUp` check for iOS video player `bufferingEnd` event and `bufferingStart` event. +* Fixes missing `isPlaybackLikelyToKeepUp` check for iOS video player `bufferingEnd` event and `bufferingStart` event. ## 2.4.7 -- Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. -- Adds iOS exception on incorrect asset path +* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. +* Adds iOS exception on incorrect asset path ## 2.4.6 -- Fixes hang when seeking to end of video. +* Fixes hang when seeking to end of video. ## 2.4.5 -- Updates functions without a prototype to avoid deprecation warning. +* Updates functions without a prototype to avoid deprecation warning. ## 2.4.4 -- Updates pigeon to fix warnings with clang 15. +* Updates pigeon to fix warnings with clang 15. ## 2.4.3 -- Synchronizes `VideoPlayerValue.isPlaying` with `AVPlayer`. +* Synchronizes `VideoPlayerValue.isPlaying` with `AVPlayer`. ## 2.4.2 -- Makes seekTo async and only complete when AVPlayer.seekTo completes. +* Makes seekTo async and only complete when AVPlayer.seekTo completes. ## 2.4.1 -- Clarifies explanation of endorsement in README. -- Aligns Dart and Flutter SDK constraints. +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. ## 2.4.0 -- Updates minimum Flutter version to 3.3 and iOS 11. +* Updates minimum Flutter version to 3.3 and iOS 11. ## 2.3.9 -- Updates links for the merge of flutter/plugins into flutter/packages. -- Updates minimum Flutter version to 3.0. +* Updates links for the merge of flutter/plugins into flutter/packages. +* Updates minimum Flutter version to 3.0. ## 2.3.8 -- Adds compatibilty with version 6.0 of the platform interface. -- Fixes file URI construction in example. -- Updates code for new analysis options. -- Adds an integration test for a bug where the aspect ratios of some HLS videos are incorrectly inverted. -- Removes an unnecessary override in example code. +* Adds compatibilty with version 6.0 of the platform interface. +* Fixes file URI construction in example. +* Updates code for new analysis options. +* Adds an integration test for a bug where the aspect ratios of some HLS videos are incorrectly inverted. +* Removes an unnecessary override in example code. ## 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. +* 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 -- Fixes a bug in iOS 16 where videos from protected live streams are not shown. -- Updates minimum Flutter version to 2.10. -- Fixes violations of new analysis option use_named_constants. -- Fixes avoid_redundant_argument_values lint warnings and minor typos. -- Ignores unnecessary import warnings in preparation for [upcoming Flutter changes](https://github.com/flutter/flutter/pull/106316). +* Fixes a bug in iOS 16 where videos from protected live streams are not shown. +* Updates minimum Flutter version to 2.10. +* Fixes violations of new analysis option use_named_constants. +* Fixes avoid_redundant_argument_values lint warnings and minor typos. +* Ignores unnecessary import warnings in preparation for [upcoming Flutter changes](https://github.com/flutter/flutter/pull/106316). ## 2.3.5 -- Updates references to the obsolete master branch. +* Updates references to the obsolete master branch. ## 2.3.4 -- Removes unnecessary imports. -- Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors +* Removes unnecessary imports. +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors lint warnings. ## 2.3.3 -- Fix XCUITest based on the new voice over announcement for tooltips. +* Fix XCUITest based on the new voice over announcement for tooltips. See: https://github.com/flutter/flutter/pull/87684 ## 2.3.2 -- Applies the standardized transform for videos with different orientations. +* Applies the standardized transform for videos with different orientations. ## 2.3.1 -- Renames internal method channels to avoid potential confusion with the +* Renames internal method channels to avoid potential confusion with the default implementation's method channel. -- Updates Pigeon to 2.0.1. +* Updates Pigeon to 2.0.1. ## 2.3.0 -- Updates Pigeon to ^1.0.16. +* Updates Pigeon to ^1.0.16. ## 2.2.18 -- Wait to initialize m3u8 videos until size is set, fixing aspect ratio. -- Adjusts test timeouts for network-dependent native tests to avoid flake. +* Wait to initialize m3u8 videos until size is set, fixing aspect ratio. +* Adjusts test timeouts for network-dependent native tests to avoid flake. ## 2.2.17 -- Splits from `video_player` as a federated implementation. +* Splits from `video_player` as a federated implementation. From cea9254d4ebba0cc97736f7b28530d8173ed0db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 11:38:17 +0100 Subject: [PATCH 076/167] Update public_header_files path for iOS --- .../darwin/video_player_avfoundation.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec index 94281a6dc0d..1867ac65221 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec @@ -18,7 +18,7 @@ Downloaded by pub (not CocoaPods). s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/*' s.osx.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_macos/*' s.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation/include/**/*.h' - s.ios.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/include/*.h' + s.ios.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/include/**/*.h' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' From 9ef93558e58da7ca482f1937257963faa0a85aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 12:19:00 +0100 Subject: [PATCH 077/167] Rename playersByTextureId to playersById --- .../darwin/RunnerTests/VideoPlayerTests.m | 22 ++++---- .../FVPVideoPlayerPlugin.m | 55 +++++++++---------- .../FVPVideoPlayerPlugin_Test.h | 2 +- .../FVPNativeVideoViewFactory.m | 9 ++- .../include/FVPNativeVideoViewFactory.h | 5 +- 5 files changed, 45 insertions(+), 48 deletions(-) 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 038797116c9..17a2ae1cb22 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -187,7 +187,7 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom XCTAssertNil(error); XCTAssertNotNil(textureId); FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present."); @@ -279,7 +279,7 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { OCMVerify([mockDisplayLink setRunning:YES]); FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -346,7 +346,7 @@ - (void)testInitStartsDisplayLinkTemporarily { .andReturn(fakeBufferRef); // Simulate a callback from the engine to request a new frame. FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; [player copyPixelBuffer]; // Since a frame was found, and the video is paused, the display link should be paused again. OCMVerify([mockDisplayLink setRunning:NO]); @@ -399,7 +399,7 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { OCMVerify([mockDisplayLink setRunning:YES]); FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -480,14 +480,14 @@ - (void)testDeregistersFromPlayer { NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [self keyValueObservingExpectationForObject:avPlayer keyPath:@"currentItem" expectedValue:nil]; [videoPlayerPlugin disposePlayer:textureId.integerValue error:&error]; - XCTAssertEqual(videoPlayerPlugin.playersByTextureId.count, 0); + XCTAssertEqual(videoPlayerPlugin.playersById.count, 0); XCTAssertNil(error); [self waitForExpectationsWithTimeout:30.0 handler:nil]; @@ -514,7 +514,7 @@ - (void)testBufferingStateFromPlayer { NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [avPlayer play]; @@ -694,7 +694,7 @@ - (void)testSeekToleranceWhenSeekingToEnd { initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; @@ -763,7 +763,7 @@ - (void)testDoesNotCrashOnRateObservationAfterDisposal { XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); weakPlayer = player; avPlayer = player.player; @@ -820,7 +820,7 @@ - (void)testHotReloadDoesNotCrash { XCTAssertNotNil(textureId); FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersByTextureId[textureId]; + (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); weakPlayer = player; @@ -897,7 +897,7 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { viewType:[[FVPPlatformVideoViewTypeBox alloc] initWithValue:FVPPlatformVideoViewTypePlatformView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); [self keyValueObservingExpectationForObject:(id)player.player.currentItem 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 4cb5d770636..4b62f030b15 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 @@ -11,9 +11,8 @@ #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" -#import "./include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h" #import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" -// Relative path is needed for messages.g.h. See: +// Relative path is needed for messages.g.h. See // https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 #import "./include/video_player_avfoundation/messages.g.h" @@ -60,7 +59,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { // We only support platform views on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger - playersByTextureId:instance.playersByTextureId]; + playersById:instance.playersById]; [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; #endif SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); @@ -82,13 +81,13 @@ - (instancetype)initWithAVFactory:(id)avFactory _registrar = registrar; _displayLinkFactory = displayLinkFactory ?: [[FVPDefaultDisplayLinkFactory alloc] init]; _avFactory = avFactory ?: [[FVPDefaultAVFactory alloc] init]; - _playersByTextureId = [NSMutableDictionary dictionaryWithCapacity:1]; + _playersById = [NSMutableDictionary dictionaryWithCapacity:1]; return self; } - (void)detachFromEngineForRegistrar:(NSObject *)registrar { - [self.playersByTextureId.allValues makeObjectsPerformSelector:@selector(disposeSansEventChannel)]; - [self.playersByTextureId removeAllObjects]; + [self.playersById.allValues makeObjectsPerformSelector:@selector(disposeSansEventChannel)]; + [self.playersById removeAllObjects]; SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, nil); } @@ -111,7 +110,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater binaryMessenger:_messenger]; [eventChannel setStreamHandler:player]; player.eventChannel = eventChannel; - self.playersByTextureId[@(playerId)] = player; + self.playersById[@(playerId)] = player; if (usesTextureApproach) { // Ensure that the first frame is drawn once available, even if the video isn't played, since @@ -128,12 +127,12 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; #endif - [self.playersByTextureId + [self.playersById enumerateKeysAndObjectsUsingBlock:^(NSNumber *textureId, FVPVideoPlayer *player, BOOL *stop) { [self.registry unregisterTexture:textureId.unsignedIntegerValue]; [player dispose]; }]; - [self.playersByTextureId removeAllObjects]; + [self.playersById removeAllObjects]; } - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options @@ -195,47 +194,47 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } -- (void)disposePlayer:(NSInteger)textureId error:(FlutterError **)error { - NSNumber *playerKey = @(textureId); - FVPVideoPlayer *player = self.playersByTextureId[playerKey]; +- (void)disposePlayer:(NSInteger)playerId error:(FlutterError **)error { + NSNumber *playerKey = @(playerId); + FVPVideoPlayer *player = self.playersById[playerKey]; if ([player isKindOfClass:[FVPVideoPlayerTextureApproach class]]) { - [self.registry unregisterTexture:textureId]; + [self.registry unregisterTexture:playerId]; } - [self.playersByTextureId removeObjectForKey:playerKey]; + [self.playersById removeObjectForKey:playerKey]; if (!player.disposed) { [player dispose]; } } -- (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; player.isLooping = isLooping; } -- (void)setVolume:(double)volume forPlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (void)setVolume:(double)volume forPlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; [player setVolume:volume]; } -- (void)setPlaybackSpeed:(double)speed forPlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (void)setPlaybackSpeed:(double)speed forPlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; [player setPlaybackSpeed:speed]; } -- (void)playPlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (void)playPlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; [player play]; } -- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (nullable NSNumber *)positionForPlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; return @([player position]); } - (void)seekTo:(NSInteger)position - forPlayer:(NSInteger)textureId + forPlayer:(NSInteger)playerId completion:(nonnull void (^)(FlutterError *_Nullable))completion { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; + FVPVideoPlayer *player = self.playersById[@(playerId)]; [player seekTo:position completionHandler:^(BOOL finished) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -244,8 +243,8 @@ - (void)seekTo:(NSInteger)position }]; } -- (void)pausePlayer:(NSInteger)textureId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersByTextureId[@(textureId)]; +- (void)pausePlayer:(NSInteger)playerId error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersById[@(playerId)]; [player pause]; } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h index e045210e68c..3737f73e602 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h @@ -19,7 +19,7 @@ @interface FVPVideoPlayerPlugin () @property(readonly, strong, nonatomic) - NSMutableDictionary *playersByTextureId; + NSMutableDictionary *playersById; - (instancetype)initWithAVFactory:(id)avFactory displayLinkFactory:(id)displayLinkFactory diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index fe60b2e0f9b..dc4938dfc1d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -10,15 +10,14 @@ @implementation FVPNativeVideoViewFactory { NSObject *_messenger; - NSMutableDictionary *_playersByTextureId; + NSMutableDictionary *_playersById; } - (instancetype)initWithMessenger:(NSObject *)messenger - playersByTextureId: - (NSMutableDictionary *)playersByTextureId { + playersById:(NSMutableDictionary *)playersById { self = [super init]; if (self) { _messenger = messenger; - _playersByTextureId = playersByTextureId; + _playersById = playersById; } return self; } @@ -27,7 +26,7 @@ - (instancetype)initWithMessenger:(NSObject *)messenger viewIdentifier:(int64_t)viewId arguments:(FVPPlatformVideoViewCreationParams *)args { NSNumber *playerId = @(args.playerId); - FVPVideoPlayer *player = _playersByTextureId[playerId]; + FVPVideoPlayer *player = _playersById[playerId]; return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h index ac0a94a40c2..4276108e65e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h @@ -10,8 +10,7 @@ /// Flutter app. @interface FVPNativeVideoViewFactory : NSObject /// Initializes a new instance of FVPNativeVideoViewFactory with the given messenger and -/// playersByTextureId dictionary which stores the video players associated with the texture IDs. +/// playersById dictionary which stores the video players associated with their IDs. - (instancetype)initWithMessenger:(NSObject *)messenger - playersByTextureId: - (NSMutableDictionary *)playersByTextureId; + playersById:(NSMutableDictionary *)playersById; @end From 120e7569bc222f6833d724b576925c38e2ad2a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 12:21:33 +0100 Subject: [PATCH 078/167] Move initWithPlayerItem from the public interface to class extension --- .../video_player_avfoundation/FVPVideoPlayer.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index acb73fbe800..dbbc9b83f43 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -44,12 +44,6 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display -/// link, AV factory, and registrar. -- (instancetype)initWithPlayerItem:(AVPlayerItem *)item - avFactory:(id)avFactory - registrar:(NSObject *)registrar; - /// Disposes the video player and releases any resources it holds. - (void)dispose; @@ -91,6 +85,12 @@ NS_ASSUME_NONNULL_BEGIN /// Indicates whether the video player has been initialized. @property(nonatomic, readonly) BOOL isInitialized; +/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display +/// link, AV factory, and registrar. +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + /// Updates the playing state of the video player. - (void)updatePlayingState; @end From 5e8b820580f8e421032d3c37b969629167bb157d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 12:31:36 +0100 Subject: [PATCH 079/167] Remove nullable and nonnull annotations from implementation file --- .../FVPVideoPlayerTextureApproach.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m index d9d96dcb095..f90b46dfae0 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m @@ -6,11 +6,11 @@ @interface FVPVideoPlayerTextureApproach () // The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; +@property(nonatomic, readonly) CALayer *flutterViewLayer; // The updater that drives callbacks to the engine to indicate that a new frame is ready. -@property(nonatomic, nullable) FVPFrameUpdater *frameUpdater; +@property(nonatomic) FVPFrameUpdater *frameUpdater; // The display link that drives frameUpdater. -@property(nonatomic, nullable) FVPDisplayLink *displayLink; +@property(nonatomic) FVPDisplayLink *displayLink; // Whether a new frame needs to be provided to the engine regardless of the current play/pause state // (e.g., after a seek while paused). If YES, the display link should continue to run until the next // frame is successfully provided. @@ -89,7 +89,6 @@ - (void)updatePlayingState { } - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { - // FIXME Rethink if it's possible to reuse it (same logic in super class) CMTime previousCMTime = self.player.currentTime; CMTime targetCMTime = CMTimeMake(location, 1000); CMTimeValue duration = self.player.currentItem.asset.duration.value; From cfe51ab9789322a44a22a7cb4f7c0c6d2f7a5493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 12:31:49 +0100 Subject: [PATCH 080/167] Add empty lines at the end of files --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 2 +- .../video_player_avfoundation/FVPVideoPlayerTextureApproach.h | 2 +- .../Sources/video_player_avfoundation_ios/FVPNativeVideoView.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index dbbc9b83f43..899e164f8ee 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -95,4 +95,4 @@ NS_ASSUME_NONNULL_BEGIN - (void)updatePlayingState; @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index 7a887a16cb4..e5dcd6420f9 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -34,4 +34,4 @@ NS_ASSUME_NONNULL_BEGIN - (void)expectFrame; @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 14472cfc8b5..805c87f3344 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -40,4 +40,4 @@ - (void)dealloc { _view = nil; } -@end \ No newline at end of file +@end From 1d21f1821109c7da74512aaa5907c35dd10cbdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 13:00:38 +0100 Subject: [PATCH 081/167] Improve imports --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 6 +++--- .../FVPVideoPlayerTextureApproach.h | 2 +- .../Sources/video_player_avfoundation_ios/FVPDisplayLink.m | 4 ++-- .../video_player_avfoundation_ios/FVPNativeVideoView.m | 4 ++-- .../FVPNativeVideoViewFactory.m | 4 ++-- .../include/FVPNativeVideoView.h | 1 + 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 899e164f8ee..b89ac64c87c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -23,13 +23,13 @@ NS_ASSUME_NONNULL_BEGIN /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; /// The AVPlayer instance used for video playback. -@property(readonly, nonatomic) AVPlayer *player; +@property(nonatomic, readonly) AVPlayer *player; /// Indicates whether the video player has been disposed. @property(nonatomic, readonly) BOOL disposed; /// Indicates whether the video player is set to loop. @property(nonatomic) BOOL isLooping; /// The current playback position of the video, in milliseconds. -@property(readonly, nonatomic) int64_t position; +@property(nonatomic, readonly) int64_t position; /// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, /// AV factory, and registrar. @@ -71,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer () /// The AVPlayerItemVideoOutput associated with this video player. -@property(readonly, nonatomic) AVPlayerItemVideoOutput *videoOutput; +@property(nonatomic, readonly) AVPlayerItemVideoOutput *videoOutput; /// The plugin registrar, to obtain view information from. @property(nonatomic, readonly) NSObject *registrar; /// The CALayer associated with the Flutter view this plugin is associated with, if any. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h index e5dcd6420f9..ee3b5dffe8d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h @@ -4,7 +4,7 @@ #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" -#import "FVPVideoPlayer_Test.h" +#import "FVPVideoPlayer.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m index c3921496a35..9bdb321ae16 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPDisplayLink.m @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPDisplayLink.h" + #import #import -#import "FVPDisplayLink.h" - /// A proxy object to act as a CADisplayLink target, to avoid retain loops, since FVPDisplayLink /// owns its CADisplayLink, but CADisplayLink retains its target. @interface FVPDisplayLinkTarget : NSObject diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 805c87f3344..fb9b85d867c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import - #import "./include/FVPNativeVideoView.h" +#import + @interface FVPPlayerView : UIView @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index dc4938dfc1d..2c4222cf94f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "./include/FVPNativeVideoViewFactory.h" + #import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" #import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" - #import "./include/FVPNativeVideoView.h" -#import "./include/FVPNativeVideoViewFactory.h" @implementation FVPNativeVideoViewFactory { NSObject *_messenger; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h index ed5f4d6d157..b1b6d3ec012 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h @@ -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 #import /// A class used to create a native video view that can be embedded in a Flutter app. From 6616a6a7da2bec7e40a4e099ab20c9094c053c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 13:26:38 +0100 Subject: [PATCH 082/167] Replace fixme comment with a regular comment --- .../example/ios/RunnerUITests/VideoPlayerUITests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m b/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m index 778caa0c308..cebe79bde3f 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m +++ b/packages/video_player/video_player_avfoundation/example/ios/RunnerUITests/VideoPlayerUITests.m @@ -27,7 +27,7 @@ - (void)testPlayVideo { XCTAssertTrue([remoteTab waitForExistenceWithTimeout:30.0]); XCTAssertTrue([remoteTab.label containsString:@"Remote"]); - // FIXME Is this a good way to check platform view? + // Go through both platform view and texture view. for (NSString *tabName in @[ @"Platform view", @"Texture view" ]) { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label BEGINSWITH %@", tabName]; XCUIElement *viewTypeTab = [app.staticTexts elementMatchingPredicate:predicate]; From a4d82b27cde891f6839f204fbde2d4bbe6470b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 15:13:26 +0100 Subject: [PATCH 083/167] Update names and doc comments in platform interface --- .../test/avfoundation_video_player_test.dart | 4 ++-- .../lib/video_player_platform_interface.dart | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index d23c73dd20a..da848cdc306 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -200,14 +200,14 @@ void main() { }); test('create with platform view', () async { - final int? textureId = await player.create(DataSource( + final int? playerId = await player.create(DataSource( sourceType: DataSourceType.file, uri: 'someUri', viewType: VideoViewType.platformView, )); expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.platformView); - expect(textureId, 3); + expect(playerId, 3); }); test('setLooping', () async { diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 5b2bb0aed1b..f0a696c494b 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -48,7 +48,8 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('dispose() has not been implemented.'); } - /// Creates an instance of a video player and returns its textureId. + /// Creates an instance of a video player and returns its playerId. + /// If view type is [VideoViewType.textureView], the playerId is also the texture id. Future create(DataSource dataSource) { throw UnimplementedError('create() has not been implemented.'); } @@ -93,6 +94,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('getPosition() has not been implemented.'); } + // TODO(FirentisTFW): Rename textureId to playerId everywhere. /// Returns a widget displaying the video with a given textureID. @Deprecated('Use buildViewWithOptions() instead.') Widget buildView(int textureId) { @@ -211,10 +213,10 @@ enum VideoFormat { /// The type of video view to be used. enum VideoViewType { - /// Uses a texture view for rendering video. + /// Texture will be used to render video. textureView, - /// Uses a platform view for rendering video. + /// Platform view will be used to render video. platformView, } From b267d3dddcfbf2c69f316097cced7448a4080c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 15:21:22 +0100 Subject: [PATCH 084/167] Update changelogs --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 2 +- .../video_player/video_player_platform_interface/CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 7e19c39689a..425df6e9b91 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.7.0 -* Adds support for platform views as the optional way of displaying a video. +* Adds support for platform views as an optional way of displaying a video. ## 2.6.4 diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index 471cde8298d..0da975b285b 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.3.0 + +* Adds support for platform views as an optional way of displaying a video. + ## 6.2.3 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. From b19ca8665e2d5254bfb46972dc5ead3d7792f8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 15:22:34 +0100 Subject: [PATCH 085/167] Bump platform_interface version to 6.3.0 --- .../video_player/video_player_platform_interface/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml index 7ed49e9e2d3..c714334fcf9 100644 --- a/packages/video_player/video_player_platform_interface/pubspec.yaml +++ b/packages/video_player/video_player_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/video_player/ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.2.3 +version: 6.3.0 environment: sdk: ^3.3.0 From f04ed067282b80b886a940f8ee8c7762d9c62711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 5 Dec 2024 17:05:41 +0100 Subject: [PATCH 086/167] Rename textureId to playerId in test file when using platform view --- .../darwin/RunnerTests/VideoPlayerTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 17a2ae1cb22..04e187e5184 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -895,7 +895,7 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { formatHint:nil httpHeaders:@{} viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypePlatformView]]; + initWithValue:FVPPlatformVideoViewTypeTextureView]]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); From c2117a81623a4da3cfa15c412c1d9cd9186d1051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 6 Dec 2024 10:02:18 +0100 Subject: [PATCH 087/167] Add local dependency overrides for platform interface --- .../video_player/video_player/example/pubspec.yaml | 12 ++++++++++++ packages/video_player/video_player/pubspec.yaml | 10 ++++++++++ .../video_player_android/example/pubspec.yaml | 10 ++++++++++ .../video_player/video_player_android/pubspec.yaml | 8 ++++++++ .../video_player_avfoundation/example/pubspec.yaml | 10 ++++++++++ .../video_player_avfoundation/pubspec.yaml | 8 ++++++++ .../video_player_web/example/pubspec.yaml | 10 ++++++++++ packages/video_player/video_player_web/pubspec.yaml | 8 ++++++++ 8 files changed, 76 insertions(+) diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml index 25f812abeee..e3a1073ee63 100644 --- a/packages/video_player/video_player/example/pubspec.yaml +++ b/packages/video_player/video_player/example/pubspec.yaml @@ -35,3 +35,15 @@ flutter: - assets/bumble_bee_captions.srt - assets/bumble_bee_captions.vtt - assets/Audio.mp3 + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_avfoundation: + { path: ../../../../packages/video_player/video_player_avfoundation }, + video_player_platform_interface: + { + path: ../../../../packages/video_player/video_player_platform_interface, + }, + } diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 6e8b92684d7..903c611c626 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -37,3 +37,13 @@ dev_dependencies: topics: - video - video-player + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_avfoundation: + { path: ../../../packages/video_player/video_player_avfoundation }, + video_player_platform_interface: + { path: ../../../packages/video_player/video_player_platform_interface }, + } diff --git a/packages/video_player/video_player_android/example/pubspec.yaml b/packages/video_player/video_player_android/example/pubspec.yaml index 01ce43d2c53..7b6f3bbfba7 100644 --- a/packages/video_player/video_player_android/example/pubspec.yaml +++ b/packages/video_player/video_player_android/example/pubspec.yaml @@ -31,3 +31,13 @@ flutter: assets: - assets/flutter-mark-square-64.png - assets/Butterfly-209.mp4 + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { + path: ../../../../packages/video_player/video_player_platform_interface, + }, + } diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index ababc4aca4e..faabc30e7a2 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -30,3 +30,11 @@ dev_dependencies: topics: - video - video-player + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { path: ../../../packages/video_player/video_player_platform_interface }, + } diff --git a/packages/video_player/video_player_avfoundation/example/pubspec.yaml b/packages/video_player/video_player_avfoundation/example/pubspec.yaml index ea24144202f..2da4175eade 100644 --- a/packages/video_player/video_player_avfoundation/example/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/example/pubspec.yaml @@ -31,3 +31,13 @@ flutter: assets: - assets/flutter-mark-square-64.png - assets/Butterfly-209.mp4 + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { + path: ../../../../packages/video_player/video_player_platform_interface, + }, + } diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 21f10e6e75f..2b1000396bb 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -34,3 +34,11 @@ dev_dependencies: topics: - video - video-player + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { path: ../../../packages/video_player/video_player_platform_interface }, + } diff --git a/packages/video_player/video_player_web/example/pubspec.yaml b/packages/video_player/video_player_web/example/pubspec.yaml index 56662e0764e..991a5c92224 100644 --- a/packages/video_player/video_player_web/example/pubspec.yaml +++ b/packages/video_player/video_player_web/example/pubspec.yaml @@ -18,3 +18,13 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { + path: ../../../../packages/video_player/video_player_platform_interface, + }, + } diff --git a/packages/video_player/video_player_web/pubspec.yaml b/packages/video_player/video_player_web/pubspec.yaml index 0985ee1297b..46cf1cebb83 100644 --- a/packages/video_player/video_player_web/pubspec.yaml +++ b/packages/video_player/video_player_web/pubspec.yaml @@ -31,3 +31,11 @@ dev_dependencies: topics: - video - video-player + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + { + video_player_platform_interface: + { path: ../../../packages/video_player/video_player_platform_interface }, + } From e7404e3f41fccd1bf982c51704b8ff60c49103b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 6 Dec 2024 12:26:44 +0100 Subject: [PATCH 088/167] Format generated iOS files --- .../video_player_avfoundation/messages.g.h | 56 +++-- .../video_player_avfoundation/messages.g.m | 214 ++++++++++++------ 2 files changed, 175 insertions(+), 95 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h index 7f545d7575c..96a8d2e51ca 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h @@ -32,25 +32,25 @@ typedef NS_ENUM(NSUInteger, FVPPlatformVideoViewType) { @interface FVPPlatformVideoViewCreationParams : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithPlayerId:(NSInteger )playerId; -@property(nonatomic, assign) NSInteger playerId; ++ (instancetype)makeWithPlayerId:(NSInteger)playerId; +@property(nonatomic, assign) NSInteger playerId; @end @interface FVPCreationOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType; -@property(nonatomic, copy, nullable) NSString * asset; -@property(nonatomic, copy, nullable) NSString * uri; -@property(nonatomic, copy, nullable) NSString * packageName; -@property(nonatomic, copy, nullable) NSString * formatHint; -@property(nonatomic, copy) NSDictionary * httpHeaders; -@property(nonatomic, strong, nullable) FVPPlatformVideoViewTypeBox * viewType; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType; +@property(nonatomic, copy, nullable) NSString *asset; +@property(nonatomic, copy, nullable) NSString *uri; +@property(nonatomic, copy, nullable) NSString *packageName; +@property(nonatomic, copy, nullable) NSString *formatHint; +@property(nonatomic, copy) NSDictionary *httpHeaders; +@property(nonatomic, strong, nullable) FVPPlatformVideoViewTypeBox *viewType; @end /// The codec used by all APIs. @@ -59,21 +59,35 @@ NSObject *FVPGetMessagesCodec(void); @protocol FVPAVFoundationVideoPlayerApi - (void)initialize:(FlutterError *_Nullable *_Nonnull)error; /// @return `nil` only when `error != nil`. -- (nullable NSNumber *)createWithOptions:(FVPCreationOptions *)creationOptions error:(FlutterError *_Nullable *_Nonnull)error; +- (nullable NSNumber *)createWithOptions:(FVPCreationOptions *)creationOptions + error:(FlutterError *_Nullable *_Nonnull)error; - (void)disposePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setVolume:(double)volume forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)setPlaybackSpeed:(double)speed forPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setLooping:(BOOL)isLooping + forPlayer:(NSInteger)textureId + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setVolume:(double)volume + forPlayer:(NSInteger)textureId + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setPlaybackSpeed:(double)speed + forPlayer:(NSInteger)textureId + error:(FlutterError *_Nullable *_Nonnull)error; - (void)playPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; /// @return `nil` only when `error != nil`. -- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)seekTo:(NSInteger)position forPlayer:(NSInteger)textureId completion:(void (^)(FlutterError *_Nullable))completion; +- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)seekTo:(NSInteger)position + forPlayer:(NSInteger)textureId + completion:(void (^)(FlutterError *_Nullable))completion; - (void)pausePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setMixWithOthers:(BOOL)mixWithOthers error:(FlutterError *_Nullable *_Nonnull)error; @end -extern void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *_Nullable api); +extern void SetUpFVPAVFoundationVideoPlayerApi( + id binaryMessenger, + NSObject *_Nullable api); -extern void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *_Nullable api, NSString *messageChannelSuffix); +extern void SetUpFVPAVFoundationVideoPlayerApiWithSuffix( + id binaryMessenger, + NSObject *_Nullable api, NSString *messageChannelSuffix); NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index 3cf2c9d15bd..cfb34884ad6 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -54,13 +54,15 @@ + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list; @end @implementation FVPPlatformVideoViewCreationParams -+ (instancetype)makeWithPlayerId:(NSInteger )playerId { - FVPPlatformVideoViewCreationParams* pigeonResult = [[FVPPlatformVideoViewCreationParams alloc] init]; ++ (instancetype)makeWithPlayerId:(NSInteger)playerId { + FVPPlatformVideoViewCreationParams *pigeonResult = + [[FVPPlatformVideoViewCreationParams alloc] init]; pigeonResult.playerId = playerId; return pigeonResult; } + (FVPPlatformVideoViewCreationParams *)fromList:(NSArray *)list { - FVPPlatformVideoViewCreationParams *pigeonResult = [[FVPPlatformVideoViewCreationParams alloc] init]; + FVPPlatformVideoViewCreationParams *pigeonResult = + [[FVPPlatformVideoViewCreationParams alloc] init]; pigeonResult.playerId = [GetNullableObjectAtIndex(list, 0) integerValue]; return pigeonResult; } @@ -76,12 +78,12 @@ + (nullable FVPPlatformVideoViewCreationParams *)nullableFromList:(NSArray * @implementation FVPCreationOptions + (instancetype)makeWithAsset:(nullable NSString *)asset - uri:(nullable NSString *)uri - packageName:(nullable NSString *)packageName - formatHint:(nullable NSString *)formatHint - httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { - FVPCreationOptions* pigeonResult = [[FVPCreationOptions alloc] init]; + uri:(nullable NSString *)uri + packageName:(nullable NSString *)packageName + formatHint:(nullable NSString *)formatHint + httpHeaders:(NSDictionary *)httpHeaders + viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { + FVPCreationOptions *pigeonResult = [[FVPCreationOptions alloc] init]; pigeonResult.asset = asset; pigeonResult.uri = uri; pigeonResult.packageName = packageName; @@ -122,11 +124,13 @@ - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 129: { NSNumber *enumAsNumber = [self readValue]; - return enumAsNumber == nil ? nil : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + return enumAsNumber == nil + ? nil + : [[FVPPlatformVideoViewTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; } - case 130: + case 130: return [FVPPlatformVideoViewCreationParams fromList:[self readValue]]; - case 131: + case 131: return [FVPCreationOptions fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -169,25 +173,35 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ - FVPMessagesPigeonCodecReaderWriter *readerWriter = [[FVPMessagesPigeonCodecReaderWriter alloc] init]; + FVPMessagesPigeonCodecReaderWriter *readerWriter = + [[FVPMessagesPigeonCodecReaderWriter alloc] init]; sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; }); return sSharedObject; } -void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, NSObject *api) { +void SetUpFVPAVFoundationVideoPlayerApi(id binaryMessenger, + NSObject *api) { SetUpFVPAVFoundationVideoPlayerApiWithSuffix(binaryMessenger, api, @""); } -void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, NSObject *api, NSString *messageChannelSuffix) { - messageChannelSuffix = messageChannelSuffix.length > 0 ? [NSString stringWithFormat: @".%@", messageChannelSuffix] : @""; +void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id binaryMessenger, + NSObject *api, + NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 + ? [NSString stringWithFormat:@".%@", messageChannelSuffix] + : @""; { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.initialize", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(initialize:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", api); + NSCAssert([api respondsToSelector:@selector(initialize:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(initialize:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { FlutterError *error; [api initialize:&error]; @@ -198,13 +212,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.create", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.create", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(createWithOptions:error:)", api); + NSCAssert([api respondsToSelector:@selector(createWithOptions:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(createWithOptions:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; FVPCreationOptions *arg_creationOptions = GetNullableObjectAtIndex(args, 0); @@ -217,13 +236,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.dispose", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(disposePlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(disposePlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(disposePlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -236,13 +260,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setLooping", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setLooping:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setLooping:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setLooping:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_isLooping = [GetNullableObjectAtIndex(args, 0) boolValue]; @@ -256,13 +285,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setVolume", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setVolume:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setVolume:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setVolume:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_volume = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -276,13 +310,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setPlaybackSpeed", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setPlaybackSpeed:forPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(setPlaybackSpeed:forPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setPlaybackSpeed:forPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_speed = [GetNullableObjectAtIndex(args, 0) doubleValue]; @@ -296,13 +335,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.play", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(playPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", api); + NSCAssert( + [api respondsToSelector:@selector(playPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(playPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -315,13 +359,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.getPosition", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(positionForPlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(positionForPlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(positionForPlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -334,33 +383,45 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.seekTo", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(seekTo:forPlayer:completion:)", api); + NSCAssert([api respondsToSelector:@selector(seekTo:forPlayer:completion:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(seekTo:forPlayer:completion:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_position = [GetNullableObjectAtIndex(args, 0) integerValue]; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; - [api seekTo:arg_position forPlayer:arg_textureId completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api seekTo:arg_position + forPlayer:arg_textureId + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.pause", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(pausePlayer:error:)", api); + NSCAssert([api respondsToSelector:@selector(pausePlayer:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(pausePlayer:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; @@ -373,13 +434,18 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin } } { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers", messageChannelSuffix] + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.video_player_avfoundation." + @"AVFoundationVideoPlayerApi.setMixWithOthers", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FVPGetMessagesCodec()]; + codec:FVPGetMessagesCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to @selector(setMixWithOthers:error:)", api); + NSCAssert([api respondsToSelector:@selector(setMixWithOthers:error:)], + @"FVPAVFoundationVideoPlayerApi api (%@) doesn't respond to " + @"@selector(setMixWithOthers:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_mixWithOthers = [GetNullableObjectAtIndex(args, 0) boolValue]; From d3f3873800fd906cce92b99d1f4b0d50124588b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 6 Dec 2024 12:34:15 +0100 Subject: [PATCH 089/167] Add native view factory import to test file --- .../darwin/RunnerTests/VideoPlayerTests.m | 5 +++++ 1 file changed, 5 insertions(+) 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 04e187e5184..e5d9aa54309 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -10,6 +10,11 @@ #import #import #import +#import + +#if TARGET_OS_IOS +#import +#endif // TODO(stuartmorgan): Convert to using mock registrars instead. NSObject *GetPluginRegistry(void) { From 0ca8f8097e08344fc50ac42597cd9bfad2f948bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 6 Dec 2024 12:45:50 +0100 Subject: [PATCH 090/167] Fix iOS source files path in podspec --- .../darwin/video_player_avfoundation.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec index 1867ac65221..a5b893c186f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec @@ -15,7 +15,7 @@ Downloaded by pub (not CocoaPods). s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation' } s.documentation_url = 'https://pub.dev/packages/video_player' s.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation/**/*.{h,m}' - s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/*' + s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/**/*' s.osx.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_macos/*' s.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation/include/**/*.h' s.ios.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/include/**/*.h' From 5f31fc3cee96913d3d7c2c7d5ad4d9f04df9bb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 6 Dec 2024 13:53:13 +0100 Subject: [PATCH 091/167] Add iOS include path to Package.swift --- .../darwin/video_player_avfoundation/Package.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift index 32bd171e33e..f36bea2dd0b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift @@ -33,7 +33,8 @@ let package = Package( .target( name: "video_player_avfoundation_ios", cSettings: [ - .headerSearchPath("../video_player_avfoundation/include/video_player_avfoundation") + .headerSearchPath("../video_player_avfoundation/include/video_player_avfoundation"), + .headerSearchPath("include"), ] ), .target( From b78b61eba828ac5db15f7c088b4632cf8f08428a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 10 Dec 2024 09:30:48 +0100 Subject: [PATCH 092/167] Revert "Remove placeholder files which are not needed anymore" This reverts commit eba2c3666bd5d4e23c87e63163289aeed5e680b4. --- .../Sources/video_player_avfoundation_ios/include/.gitkeep | 0 .../video_player_avfoundation_ios/include/FVPEmpty.h | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h new file mode 100644 index 00000000000..c7b344f7299 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPEmpty.h @@ -0,0 +1,6 @@ +// 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. + +// Empty file to perserve include directory in pub-cache. See +// https://github.com/flutter/flutter/issues/148002 for more information. From dbe39bad6e6bca0ac8950ea0066b2cee2bb86885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 10 Dec 2024 11:18:56 +0100 Subject: [PATCH 093/167] Move header files related to platform views to the main directory --- .../darwin/video_player_avfoundation.podspec | 3 +-- .../video_player_avfoundation/Package.swift | 3 +-- .../FVPVideoPlayerPlugin.m | 2 +- .../FVPNativeVideoView.h | 15 ++++++++++++++- .../FVPNativeVideoViewFactory.h | 6 ++++++ .../FVPNativeVideoView.m | 2 +- .../FVPNativeVideoViewFactory.m | 4 ++-- 7 files changed, 26 insertions(+), 9 deletions(-) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation_ios/include => video_player_avfoundation/include/video_player_avfoundation}/FVPNativeVideoView.h (73%) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation_ios/include => video_player_avfoundation/include/video_player_avfoundation}/FVPNativeVideoViewFactory.h (82%) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec index a5b893c186f..81e8d2f8e4e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation.podspec @@ -15,10 +15,9 @@ Downloaded by pub (not CocoaPods). s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation' } s.documentation_url = 'https://pub.dev/packages/video_player' s.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation/**/*.{h,m}' - s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/**/*' + s.ios.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/*' s.osx.source_files = 'video_player_avfoundation/Sources/video_player_avfoundation_macos/*' s.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation/include/**/*.h' - s.ios.public_header_files = 'video_player_avfoundation/Sources/video_player_avfoundation_ios/include/**/*.h' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift index f36bea2dd0b..32bd171e33e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Package.swift @@ -33,8 +33,7 @@ let package = Package( .target( name: "video_player_avfoundation_ios", cSettings: [ - .headerSearchPath("../video_player_avfoundation/include/video_player_avfoundation"), - .headerSearchPath("include"), + .headerSearchPath("../video_player_avfoundation/include/video_player_avfoundation") ] ), .target( 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 4b62f030b15..7e6fcd2a0a5 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 @@ -18,7 +18,7 @@ #if TARGET_OS_IOS // We only support platform views on iOS as of now. -#import "../video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h" +#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #endif #if !__has_feature(objc_arc) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h similarity index 73% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index b1b6d3ec012..1e2ade54c73 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -2,16 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import +// We only support platform views on iOS as of now. Ifdefs are used to avoid compilation errors. + +#if TARGET_OS_OSX +#import +#else #import +#endif + +#import /// A class used to create a native video view that can be embedded in a Flutter app. /// This class wraps an AVPlayer instance and displays its video content. +#if TARGET_OS_IOS @interface FVPNativeVideoView : NSObject +#else +@interface FVPNativeVideoView : NSWindow +#endif /// Initializes a new instance of a native view. /// It creates a video view instance and sets the provided AVPlayer instance to it. - (instancetype)initWithPlayer:(AVPlayer *)player; +#if TARGET_OS_IOS /// Returns the native UIView that displays the video content. - (UIView *)view; +#endif @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h similarity index 82% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index 4276108e65e..c48e6d6bb53 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/include/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -2,7 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// We only support platform views on iOS as of now. Ifdef is used to avoid compilation errors. + +#if TARGET_OS_OSX +#import +#else #import +#endif #import "FVPVideoPlayer.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index fb9b85d867c..f8007ea88a3 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "./include/FVPNativeVideoView.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" #import diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 2c4222cf94f..8660770a921 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "./include/FVPNativeVideoViewFactory.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" #import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" #import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" -#import "./include/FVPNativeVideoView.h" @implementation FVPNativeVideoViewFactory { NSObject *_messenger; From 7bbf8bf9bd9ae4bf999b53101dd9883d0d375f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 10 Dec 2024 12:11:04 +0100 Subject: [PATCH 094/167] Add TargetConditionals.h import to FVPNativeVideoView.h --- .../include/video_player_avfoundation/FVPNativeVideoView.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index 1e2ade54c73..5c82c63733e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -4,6 +4,8 @@ // We only support platform views on iOS as of now. Ifdefs are used to avoid compilation errors. +#import + #if TARGET_OS_OSX #import #else From 2dac4401475983d5fdd90130ecaa03c502e09105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 10 Dec 2024 12:51:43 +0100 Subject: [PATCH 095/167] Add TargetConditionals.h import to FVPNativeVideoViewFactory.h --- .../video_player_avfoundation/FVPNativeVideoViewFactory.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index c48e6d6bb53..edce84c3610 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -4,6 +4,8 @@ // We only support platform views on iOS as of now. Ifdef is used to avoid compilation errors. +#import + #if TARGET_OS_OSX #import #else From 1b7737608599a660f79aae17f4e4b32b155d8bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 10 Dec 2024 14:28:29 +0100 Subject: [PATCH 096/167] Update doc comments for FVPVideoPlayer constructors --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index b89ac64c87c..a1151643329 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -31,14 +31,13 @@ NS_ASSUME_NONNULL_BEGIN /// The current playback position of the video, in milliseconds. @property(nonatomic, readonly) int64_t position; -/// Initializes a new instance of FVPVideoPlayer with the given asset, frame updater, display link, -/// AV factory, and registrar. +/// Initializes a new instance of FVPVideoPlayer with the given asset, AV factory, and registrar. - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Initializes a new instance of FVPVideoPlayer with the given URL, frame updater, display link, -/// HTTP headers, AV factory, and registrar. +/// Initializes a new instance of FVPVideoPlayer with the given URL, HTTP headers, AV factory, and +/// registrar. - (instancetype)initWithURL:(NSURL *)url httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory From d2778a1a4aa754601c2cc85798b3be130742eefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 10:55:21 +0100 Subject: [PATCH 097/167] Remove dependency overrides for packages that have no other changes --- .../video_player/video_player/example/pubspec.yaml | 12 ------------ packages/video_player/video_player/pubspec.yaml | 10 ---------- .../video_player_android/example/pubspec.yaml | 10 ---------- .../video_player/video_player_android/pubspec.yaml | 8 -------- .../video_player_web/example/pubspec.yaml | 10 ---------- packages/video_player/video_player_web/pubspec.yaml | 8 -------- 6 files changed, 58 deletions(-) diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml index e7d4838fe70..5755db029dd 100644 --- a/packages/video_player/video_player/example/pubspec.yaml +++ b/packages/video_player/video_player/example/pubspec.yaml @@ -35,15 +35,3 @@ flutter: - assets/bumble_bee_captions.srt - assets/bumble_bee_captions.vtt - assets/Audio.mp3 - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_avfoundation: - { path: ../../../../packages/video_player/video_player_avfoundation }, - video_player_platform_interface: - { - path: ../../../../packages/video_player/video_player_platform_interface, - }, - } diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index ac69d292bee..c19f6c6f77c 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -37,13 +37,3 @@ dev_dependencies: topics: - video - video-player - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_avfoundation: - { path: ../../../packages/video_player/video_player_avfoundation }, - video_player_platform_interface: - { path: ../../../packages/video_player/video_player_platform_interface }, - } diff --git a/packages/video_player/video_player_android/example/pubspec.yaml b/packages/video_player/video_player_android/example/pubspec.yaml index 7b6f3bbfba7..01ce43d2c53 100644 --- a/packages/video_player/video_player_android/example/pubspec.yaml +++ b/packages/video_player/video_player_android/example/pubspec.yaml @@ -31,13 +31,3 @@ flutter: assets: - assets/flutter-mark-square-64.png - assets/Butterfly-209.mp4 - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { - path: ../../../../packages/video_player/video_player_platform_interface, - }, - } diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index faabc30e7a2..ababc4aca4e 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -30,11 +30,3 @@ dev_dependencies: topics: - video - video-player - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { path: ../../../packages/video_player/video_player_platform_interface }, - } diff --git a/packages/video_player/video_player_web/example/pubspec.yaml b/packages/video_player/video_player_web/example/pubspec.yaml index 991a5c92224..56662e0764e 100644 --- a/packages/video_player/video_player_web/example/pubspec.yaml +++ b/packages/video_player/video_player_web/example/pubspec.yaml @@ -18,13 +18,3 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { - path: ../../../../packages/video_player/video_player_platform_interface, - }, - } diff --git a/packages/video_player/video_player_web/pubspec.yaml b/packages/video_player/video_player_web/pubspec.yaml index 46cf1cebb83..0985ee1297b 100644 --- a/packages/video_player/video_player_web/pubspec.yaml +++ b/packages/video_player/video_player_web/pubspec.yaml @@ -31,11 +31,3 @@ dev_dependencies: topics: - video - video-player - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { path: ../../../packages/video_player/video_player_platform_interface }, - } From 4a8d0bddd76d6b6081cc5ec1b938b1a882a20837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 10:58:20 +0100 Subject: [PATCH 098/167] Remove redundant sentence from a comment --- .../lib/src/avfoundation_video_player.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 8f509cdc6e0..13db46e3300 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -152,8 +152,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { VideoViewOptions( playerId: textureId, // Texture view was the only supported view type before - // buildViewWithOptions was introduced. We pass it here to maintain - // backwards compatibility. + // buildViewWithOptions was introduced. viewType: VideoViewType.textureView, ), ); From b6f2e2c8b90965bf02f704d98a1bad3e52b364b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 11:14:05 +0100 Subject: [PATCH 099/167] Use INT_MAX as the initial non-texture player ID, and then decrement --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 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 7e6fcd2a0a5..cb47b1a6cf2 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 @@ -41,7 +41,7 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr /// The next non-texture player ID, initialized to a high number to avoid collisions with /// texture IDs (which are generated separately). -static int64_t nextNonTexturePlayerId = 1000000; +static int64_t nextNonTexturePlayerId = INT_MAX; @interface FVPVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject *registry; @@ -100,7 +100,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater frameUpdater.textureId = playerId; } else { @synchronized(self) { - playerId = nextNonTexturePlayerId++; + playerId = nextNonTexturePlayerId--; } } From 6702c6f8a2d1a1c0ab61c213b56f92cfd6dc91ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 11:47:52 +0100 Subject: [PATCH 100/167] Make viewType parameter in CreationOptions non-nullable --- .../darwin/RunnerTests/VideoPlayerTests.m | 39 +++++++------------ .../FVPVideoPlayerPlugin.m | 2 +- .../video_player_avfoundation/messages.g.h | 4 +- .../video_player_avfoundation/messages.g.m | 7 ++-- .../lib/src/messages.g.dart | 6 +-- .../pigeons/messages.dart | 8 +++- 6 files changed, 29 insertions(+), 37 deletions(-) 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 f24544af35b..7f69329ec99 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -186,8 +186,7 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -263,8 +262,7 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -332,8 +330,7 @@ - (void)testInitStartsDisplayLinkTemporarily { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -385,8 +382,7 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -450,8 +446,7 @@ - (void)testPauseWhileWaitingForFrameDoesNotStopDisplayLink { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; @@ -480,8 +475,7 @@ - (void)testDeregistersFromPlayer { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -514,8 +508,7 @@ - (void)testBufferingStateFromPlayer { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -641,8 +634,7 @@ - (void)testSeekToleranceWhenNotSeekingToEnd { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; @@ -681,8 +673,7 @@ - (void)testSeekToleranceWhenSeekingToEnd { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; @@ -711,8 +702,7 @@ - (void)testSeekToleranceWhenSeekingToEnd { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; @@ -778,8 +768,7 @@ - (void)testDoesNotCrashOnRateObservationAfterDisposal { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -834,8 +823,7 @@ - (void)testHotReloadDoesNotCrash { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); @@ -915,8 +903,7 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypeTextureView]]; + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); 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 cb47b1a6cf2..9a72f311976 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 @@ -137,7 +137,7 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options error:(FlutterError **)error { - BOOL usesTextureApproach = options.viewType.value == FVPPlatformVideoViewTypeTextureView; + BOOL usesTextureApproach = options.viewType == FVPPlatformVideoViewTypeTextureView; FVPFrameUpdater *frameUpdater; FVPDisplayLink *displayLink; if (usesTextureApproach) { diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h index 96a8d2e51ca..cec06e43c72 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h @@ -44,13 +44,13 @@ typedef NS_ENUM(NSUInteger, FVPPlatformVideoViewType) { packageName:(nullable NSString *)packageName formatHint:(nullable NSString *)formatHint httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType; + viewType:(FVPPlatformVideoViewType)viewType; @property(nonatomic, copy, nullable) NSString *asset; @property(nonatomic, copy, nullable) NSString *uri; @property(nonatomic, copy, nullable) NSString *packageName; @property(nonatomic, copy, nullable) NSString *formatHint; @property(nonatomic, copy) NSDictionary *httpHeaders; -@property(nonatomic, strong, nullable) FVPPlatformVideoViewTypeBox *viewType; +@property(nonatomic, assign) FVPPlatformVideoViewType viewType; @end /// The codec used by all APIs. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index cfb34884ad6..74b6a4ec118 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -82,7 +82,7 @@ + (instancetype)makeWithAsset:(nullable NSString *)asset packageName:(nullable NSString *)packageName formatHint:(nullable NSString *)formatHint httpHeaders:(NSDictionary *)httpHeaders - viewType:(nullable FVPPlatformVideoViewTypeBox *)viewType { + viewType:(FVPPlatformVideoViewType)viewType { FVPCreationOptions *pigeonResult = [[FVPCreationOptions alloc] init]; pigeonResult.asset = asset; pigeonResult.uri = uri; @@ -99,7 +99,8 @@ + (FVPCreationOptions *)fromList:(NSArray *)list { pigeonResult.packageName = GetNullableObjectAtIndex(list, 2); pigeonResult.formatHint = GetNullableObjectAtIndex(list, 3); pigeonResult.httpHeaders = GetNullableObjectAtIndex(list, 4); - pigeonResult.viewType = GetNullableObjectAtIndex(list, 5); + FVPPlatformVideoViewTypeBox *boxedFVPPlatformVideoViewType = GetNullableObjectAtIndex(list, 5); + pigeonResult.viewType = boxedFVPPlatformVideoViewType.value; return pigeonResult; } + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list { @@ -112,7 +113,7 @@ + (nullable FVPCreationOptions *)nullableFromList:(NSArray *)list { self.packageName ?: [NSNull null], self.formatHint ?: [NSNull null], self.httpHeaders ?: [NSNull null], - self.viewType ?: [NSNull null], + [[FVPPlatformVideoViewTypeBox alloc] initWithValue:self.viewType], ]; } @end diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index 1b3f0e08950..acc1c8b8c70 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -64,7 +64,7 @@ class CreationOptions { this.packageName, this.formatHint, required this.httpHeaders, - this.viewType, + required this.viewType, }); String? asset; @@ -77,7 +77,7 @@ class CreationOptions { Map httpHeaders; - PlatformVideoViewType? viewType; + PlatformVideoViewType viewType; Object encode() { return [ @@ -99,7 +99,7 @@ class CreationOptions { formatHint: result[3] as String?, httpHeaders: (result[4] as Map?)!.cast(), - viewType: result[5] as PlatformVideoViewType?, + viewType: result[5]! as PlatformVideoViewType, ); } } diff --git a/packages/video_player/video_player_avfoundation/pigeons/messages.dart b/packages/video_player/video_player_avfoundation/pigeons/messages.dart index 80fef03f860..5ed49ea1eab 100644 --- a/packages/video_player/video_player_avfoundation/pigeons/messages.dart +++ b/packages/video_player/video_player_avfoundation/pigeons/messages.dart @@ -34,13 +34,17 @@ class PlatformVideoViewCreationParams { } class CreationOptions { - CreationOptions({required this.httpHeaders}); + CreationOptions({ + required this.httpHeaders, + required this.viewType, + }); + String? asset; String? uri; String? packageName; String? formatHint; Map httpHeaders; - PlatformVideoViewType? viewType; + PlatformVideoViewType viewType; } @HostApi(dartHostTestHandler: 'TestHostVideoPlayerApi') From 4d7ca153f355a69cf9b12417c948dfb58fe0bdc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:14:29 +0100 Subject: [PATCH 101/167] Rename FVPVideoPlayerTextureApproach to FVPTextureBasedVideoPlayer --- .../darwin/RunnerTests/VideoPlayerTests.m | 22 ++++++------- ...pproach.m => FVPTextureBasedVideoPlayer.m} | 6 ++-- .../FVPVideoPlayerPlugin.m | 32 +++++++++---------- ...pproach.h => FVPTextureBasedVideoPlayer.h} | 6 ++-- ...st.h => FVPTextureBasedVideoPlayer_Test.h} | 4 +-- 5 files changed, 35 insertions(+), 35 deletions(-) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/{FVPVideoPlayerTextureApproach.m => FVPTextureBasedVideoPlayer.m} (98%) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/{FVPVideoPlayerTextureApproach.h => FVPTextureBasedVideoPlayer.h} (84%) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/{FVPVideoPlayerTextureApproach_Test.h => FVPTextureBasedVideoPlayer_Test.h} (92%) 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 7f69329ec99..f540e5738d0 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -9,7 +9,7 @@ #import #import #import -#import +#import #import #if TARGET_OS_IOS @@ -190,8 +190,8 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; + FVPTextureBasedVideoPlayer *player = + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present."); @@ -281,8 +281,8 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { // Seeking to a new position should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); - FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; + FVPTextureBasedVideoPlayer *player = + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -347,8 +347,8 @@ - (void)testInitStartsDisplayLinkTemporarily { .ignoringNonObjectArgs() .andReturn(fakeBufferRef); // Simulate a callback from the engine to request a new frame. - FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; + FVPTextureBasedVideoPlayer *player = + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; [player copyPixelBuffer]; // Since a frame was found, and the video is paused, the display link should be paused again. OCMVerify([mockDisplayLink setRunning:NO]); @@ -399,8 +399,8 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { [self waitForExpectationsWithTimeout:30.0 handler:nil]; OCMVerify([mockDisplayLink setRunning:YES]); - FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; + FVPTextureBasedVideoPlayer *player = + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -828,8 +828,8 @@ - (void)testHotReloadDoesNotCrash { XCTAssertNil(error); XCTAssertNotNil(textureId); - FVPVideoPlayerTextureApproach *player = - (FVPVideoPlayerTextureApproach *)videoPlayerPlugin.playersById[textureId]; + FVPTextureBasedVideoPlayer *player = + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; XCTAssertNotNil(player); weakPlayer = player; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m similarity index 98% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index f90b46dfae0..5b26785f921 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerTextureApproach.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FVPVideoPlayerTextureApproach_Test.h" +#import "FVPTextureBasedVideoPlayer_Test.h" -@interface FVPVideoPlayerTextureApproach () +@interface FVPTextureBasedVideoPlayer () // The CALayer associated with the Flutter view this plugin is associated with, if any. @property(nonatomic, readonly) CALayer *flutterViewLayer; // The updater that drives callbacks to the engine to indicate that a new frame is ready. @@ -17,7 +17,7 @@ @interface FVPVideoPlayerTextureApproach () @property(nonatomic, assign) BOOL waitingForFrame; @end -@implementation FVPVideoPlayerTextureApproach +@implementation FVPTextureBasedVideoPlayer - (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink 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 9a72f311976..6d54e3dc157 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 @@ -10,8 +10,8 @@ #import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" +#import "./include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" -#import "./include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h" // Relative path is needed for messages.g.h. See // https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 #import "./include/video_player_avfoundation/messages.g.h" @@ -93,10 +93,10 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { BOOL usesTextureApproach = - frameUpdater != nil && [player isKindOfClass:[FVPVideoPlayerTextureApproach class]]; + frameUpdater != nil && [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; int64_t playerId; if (usesTextureApproach) { - playerId = [self.registry registerTexture:(FVPVideoPlayerTextureApproach *)player]; + playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; frameUpdater.textureId = playerId; } else { @synchronized(self) { @@ -115,7 +115,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater if (usesTextureApproach) { // Ensure that the first frame is drawn once available, even if the video isn't played, since // the engine is now expecting the texture to be populated. - [(FVPVideoPlayerTextureApproach *)player expectFrame]; + [(FVPTextureBasedVideoPlayer *)player expectFrame]; } return playerId; @@ -158,11 +158,11 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } @try { if (usesTextureApproach) { - player = [[FVPVideoPlayerTextureApproach alloc] initWithAsset:assetPath - frameUpdater:frameUpdater - displayLink:displayLink - avFactory:_avFactory - registrar:self.registrar]; + player = [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath + frameUpdater:frameUpdater + displayLink:displayLink + avFactory:_avFactory + registrar:self.registrar]; } else { player = [[FVPVideoPlayer alloc] initWithAsset:assetPath avFactory:_avFactory @@ -175,12 +175,12 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } else if (options.uri) { if (usesTextureApproach) { - player = [[FVPVideoPlayerTextureApproach alloc] initWithURL:[NSURL URLWithString:options.uri] - frameUpdater:frameUpdater - displayLink:displayLink - httpHeaders:options.httpHeaders - avFactory:_avFactory - registrar:self.registrar]; + player = [[FVPTextureBasedVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] + frameUpdater:frameUpdater + displayLink:displayLink + httpHeaders:options.httpHeaders + avFactory:_avFactory + registrar:self.registrar]; } else { player = [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] httpHeaders:options.httpHeaders @@ -197,7 +197,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options - (void)disposePlayer:(NSInteger)playerId error:(FlutterError **)error { NSNumber *playerKey = @(playerId); FVPVideoPlayer *player = self.playersById[playerKey]; - if ([player isKindOfClass:[FVPVideoPlayerTextureApproach class]]) { + if ([player isKindOfClass:[FVPTextureBasedVideoPlayer class]]) { [self.registry unregisterTexture:playerId]; } [self.playersById removeObjectForKey:playerKey]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h similarity index 84% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index ee3b5dffe8d..c877420e7e1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN /// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of /// displaying the video in the app. It manages the CALayer associated with the Flutter view, /// updates frames, and handles display link callbacks. -@interface FVPVideoPlayerTextureApproach : FVPVideoPlayer -/// Initializes a new instance of FVPVideoPlayerTextureApproach with the given URL, frame updater, +@interface FVPTextureBasedVideoPlayer : FVPVideoPlayer +/// Initializes a new instance of FVPTextureBasedVideoPlayer with the given URL, frame updater, /// display link, HTTP headers, AV factory, and registrar. - (instancetype)initWithURL:(NSURL *)url frameUpdater:(FVPFrameUpdater *)frameUpdater @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN avFactory:(id)avFactory registrar:(NSObject *)registrar; -/// Initializes a new instance of FVPVideoPlayerTextureApproach with the given asset, frame updater, +/// Initializes a new instance of FVPTextureBasedVideoPlayer with the given asset, frame updater, /// display link, AV factory, and registrar. - (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h similarity index 92% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h index a1f59e7c264..2e5366360bc 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerTextureApproach_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h @@ -8,11 +8,11 @@ #import #endif -#import "FVPVideoPlayerTextureApproach.h" +#import "FVPTextureBasedVideoPlayer.h" NS_ASSUME_NONNULL_BEGIN -@interface FVPVideoPlayerTextureApproach () +@interface FVPTextureBasedVideoPlayer () /// The AVPlayerLayer used to display the video content. /// 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 From 7bb4de35a0de9c5961374387592a58566a395458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:23:23 +0100 Subject: [PATCH 102/167] Remove redeclaration of view method from the interface --- .../include/video_player_avfoundation/FVPNativeVideoView.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index 5c82c63733e..daaefde65cf 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -24,9 +24,4 @@ /// Initializes a new instance of a native view. /// It creates a video view instance and sets the provided AVPlayer instance to it. - (instancetype)initWithPlayer:(AVPlayer *)player; - -#if TARGET_OS_IOS -/// Returns the native UIView that displays the video content. -- (UIView *)view; -#endif @end From f753253ad6a66fe2ed3cd110e3e1f659589dbfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:42:34 +0100 Subject: [PATCH 103/167] Use a block instead of passing a mutable dictionary --- .../FVPVideoPlayerPlugin.m | 4 +++- .../FVPNativeVideoViewFactory.h | 4 ++-- .../FVPNativeVideoViewFactory.m | 16 +++++++--------- 3 files changed, 12 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 6d54e3dc157..fdd0b086ca5 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 @@ -59,7 +59,9 @@ + (void)registerWithRegistrar:(NSObject *)registrar { // We only support platform views on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger - playersById:instance.playersById]; + playerByIdProvider:^FVPVideoPlayer *(NSNumber *playerId) { + return instance->_playersById[playerId]; + }]; [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; #endif SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index edce84c3610..eaf89963d8a 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -18,7 +18,7 @@ /// Flutter app. @interface FVPNativeVideoViewFactory : NSObject /// Initializes a new instance of FVPNativeVideoViewFactory with the given messenger and -/// playersById dictionary which stores the video players associated with their IDs. +/// a block that provides video players associated with their IDs. - (instancetype)initWithMessenger:(NSObject *)messenger - playersById:(NSMutableDictionary *)playersById; + playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider; @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 8660770a921..f7b000cbb8c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -1,7 +1,3 @@ -// 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 "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" @@ -10,14 +6,15 @@ @implementation FVPNativeVideoViewFactory { NSObject *_messenger; - NSMutableDictionary *_playersById; + FVPVideoPlayer * (^_playerByIdProvider)(NSNumber *); } + - (instancetype)initWithMessenger:(NSObject *)messenger - playersById:(NSMutableDictionary *)playersById { + playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { self = [super init]; if (self) { _messenger = messenger; - _playersById = playersById; + _playerByIdProvider = [playerByIdProvider copy]; } return self; } @@ -26,11 +23,12 @@ - (instancetype)initWithMessenger:(NSObject *)messenger viewIdentifier:(int64_t)viewId arguments:(FVPPlatformVideoViewCreationParams *)args { NSNumber *playerId = @(args.playerId); - FVPVideoPlayer *player = _playersById[playerId]; + FVPVideoPlayer *player = _playerByIdProvider(playerId); return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; } - (NSObject *)createArgsCodec { return FVPGetMessagesCodec(); } -@end + +@end \ No newline at end of file From 16fb48e32028dc526bfa2872a10d32eadeeb090a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:43:04 +0100 Subject: [PATCH 104/167] Do not use "we" in comments --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 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 fdd0b086ca5..1eebabcfd32 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 @@ -17,7 +17,7 @@ #import "./include/video_player_avfoundation/messages.g.h" #if TARGET_OS_IOS -// We only support platform views on iOS as of now. +// Platform views are only supported on iOS as of now. #import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #endif @@ -56,7 +56,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; #if TARGET_OS_IOS - // We only support platform views on iOS as of now. + // Platform views are only supported on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger playerByIdProvider:^FVPVideoPlayer *(NSNumber *playerId) { From b1dd3797bc4bd0fc709a96e14b84bf76a5a2eadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:49:55 +0100 Subject: [PATCH 105/167] Inherit from NSView instead of NSWindow --- .../include/video_player_avfoundation/FVPNativeVideoView.h | 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/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index daaefde65cf..da8fb6dbab8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -19,7 +19,7 @@ #if TARGET_OS_IOS @interface FVPNativeVideoView : NSObject #else -@interface FVPNativeVideoView : NSWindow +@interface FVPNativeVideoView : NSView #endif /// Initializes a new instance of a native view. /// It creates a video view instance and sets the provided AVPlayer instance to it. From 7d7121a4509847721b4d2f88ec8e51a9c2b6d2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 12:59:47 +0100 Subject: [PATCH 106/167] Do not override dealloc in FVPNativeVideoView --- .../video_player_avfoundation_ios/FVPNativeVideoView.m | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index f8007ea88a3..4e29fe86008 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -34,10 +34,4 @@ - (instancetype)initWithPlayer:(AVPlayer *)player { - (FVPPlayerView *)view { return _view; } - -- (void)dealloc { - [_view setPlayer:nil]; - _view = nil; -} - @end From 3eddd8137e7d5a5edb50e34c758d86b1895104cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 13:14:43 +0100 Subject: [PATCH 107/167] Fix typo --- .../darwin/RunnerTests/VideoPlayerTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 f540e5738d0..b3f029bb069 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -8,8 +8,8 @@ #import #import -#import #import +#import #import #if TARGET_OS_IOS @@ -126,7 +126,7 @@ - (AVPlayerItemVideoOutput *)videoOutputWithPixelBufferAttributes: #pragma mark - -/** Test implementation of FVPDisplayLinkFactory that returns a provided display link nstance. */ +/** Test implementation of FVPDisplayLinkFactory that returns a provided display link instance. */ @interface StubFVPDisplayLinkFactory : NSObject /** This display link to return. */ From 97bd78003e34d4affe04002c2a0baa4b5d0e54a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 13:34:58 +0100 Subject: [PATCH 108/167] Remove "we" from comments --- .../include/video_player_avfoundation/FVPNativeVideoView.h | 2 +- .../video_player_avfoundation/FVPNativeVideoViewFactory.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index da8fb6dbab8..8c53ac1c017 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// We only support platform views on iOS as of now. Ifdefs are used to avoid compilation errors. +// Platform views are only supported on iOS as of now. Ifdefs are used to avoid compilation errors. #import diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index eaf89963d8a..655752ded0f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// We only support platform views on iOS as of now. Ifdef is used to avoid compilation errors. +// Platform views are only supported on iOS as of now. Ifdef is used to avoid compilation errors. #import From 8fe742890773d1be9f68df106dc4953e1006faa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 13:38:18 +0100 Subject: [PATCH 109/167] Fix initialization of viewType in test file --- .../darwin/RunnerTests/VideoPlayerTests.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 b3f029bb069..83932357d21 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -226,8 +226,7 @@ - (void)testPlayerForPlatformViewDoesNotRegisterTexture { packageName:nil formatHint:nil httpHeaders:@{} - viewType:[[FVPPlatformVideoViewTypeBox alloc] - initWithValue:FVPPlatformVideoViewTypePlatformView]]; + viewType:FVPPlatformVideoViewTypePlatformView]; FlutterError *createError; [videoPlayerPlugin createWithOptions:create error:&createError]; From 9b7f9ad66ea3161970ee6db1c72e5ec4f8c6e70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 14:57:26 +0100 Subject: [PATCH 110/167] Fix (hopefully) a flaky test - wait for the assertion to happen instead of checking it straight away --- .../darwin/RunnerTests/VideoPlayerTests.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 83932357d21..9b767278f22 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -279,10 +279,14 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { // Seeking to a new position should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); - FVPTextureBasedVideoPlayer *player = (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; - XCTAssertEqual([player position], 1234); + // Wait for the player's position to update, it shouldn't take long. + XCTestExpectation *positionExpectation = + [self expectationForPredicate:[NSPredicate predicateWithFormat:@"position == 1234"] + evaluatedWithObject:player + handler:nil]; + [self waitForExpectations:@[ positionExpectation ] timeout:3.0]; // Simulate a buffer being available. OCMStub([mockVideoOutput hasNewPixelBufferForItemTime:kCMTimeZero]) From cacfd26b0fa293860ecf9b5c36412704831e6f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 15:19:53 +0100 Subject: [PATCH 111/167] Add back license that was removed by mistake --- .../video_player_avfoundation_ios/FVPNativeVideoViewFactory.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index f7b000cbb8c..050bf48e932 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -1,3 +1,7 @@ +// 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 "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" From 576a005379806f57c2b984b62e2739ee2e624164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 15:49:24 +0100 Subject: [PATCH 112/167] Rename variables for better consistency --- .../FVPVideoPlayerPlugin.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 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 1eebabcfd32..2debe191df3 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 @@ -94,10 +94,10 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { - BOOL usesTextureApproach = + BOOL textureBased = frameUpdater != nil && [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; int64_t playerId; - if (usesTextureApproach) { + if (textureBased) { playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; frameUpdater.textureId = playerId; } else { @@ -114,7 +114,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater player.eventChannel = eventChannel; self.playersById[@(playerId)] = player; - if (usesTextureApproach) { + if (textureBased) { // Ensure that the first frame is drawn once available, even if the video isn't played, since // the engine is now expecting the texture to be populated. [(FVPTextureBasedVideoPlayer *)player expectFrame]; @@ -139,10 +139,10 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options error:(FlutterError **)error { - BOOL usesTextureApproach = options.viewType == FVPPlatformVideoViewTypeTextureView; + BOOL textureBased = options.viewType == FVPPlatformVideoViewTypeTextureView; FVPFrameUpdater *frameUpdater; FVPDisplayLink *displayLink; - if (usesTextureApproach) { + if (textureBased) { frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; displayLink = [self.displayLinkFactory displayLinkWithRegistrar:_registrar callback:^() { @@ -159,7 +159,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options assetPath = [_registrar lookupKeyForAsset:options.asset]; } @try { - if (usesTextureApproach) { + if (textureBased) { player = [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath frameUpdater:frameUpdater displayLink:displayLink @@ -176,7 +176,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options return nil; } } else if (options.uri) { - if (usesTextureApproach) { + if (textureBased) { player = [[FVPTextureBasedVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] frameUpdater:frameUpdater displayLink:displayLink From b7b58e206ee92e52b15593aef4f93e7bd3db027d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 16:34:31 +0100 Subject: [PATCH 113/167] Do not use @synchronized when decrementing next player ID --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 4 +--- 1 file changed, 1 insertion(+), 3 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 2debe191df3..686b20f8035 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 @@ -101,9 +101,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; frameUpdater.textureId = playerId; } else { - @synchronized(self) { - playerId = nextNonTexturePlayerId--; - } + playerId = nextNonTexturePlayerId--; } FlutterEventChannel *eventChannel = [FlutterEventChannel From 8a71cfa584b5e7d9e44dbd595bd101d77ebaa78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 17:10:07 +0100 Subject: [PATCH 114/167] Introduce createWithOptions method --- .../example/lib/mini_controller.dart | 11 +- .../lib/src/avfoundation_video_player.dart | 20 ++- .../test/avfoundation_video_player_test.dart | 122 ++++++++++++++++-- .../lib/video_player_platform_interface.dart | 29 ++++- 4 files changed, 157 insertions(+), 25 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index 335836872c8..58898bc731d 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -231,29 +231,30 @@ class MiniController extends ValueNotifier { sourceType: DataSourceType.asset, asset: dataSource, package: package, - viewType: viewType, ); case DataSourceType.network: dataSourceDescription = DataSource( sourceType: DataSourceType.network, uri: dataSource, - viewType: viewType, ); case DataSourceType.file: dataSourceDescription = DataSource( sourceType: DataSourceType.file, uri: dataSource, - viewType: viewType, ); case DataSourceType.contentUri: dataSourceDescription = DataSource( sourceType: DataSourceType.contentUri, uri: dataSource, - viewType: viewType, ); } - _textureId = (await _platform.create(dataSourceDescription)) ?? + final VideoCreationOptions creationOptions = VideoCreationOptions( + dataSource: dataSourceDescription, + viewType: viewType, + ); + + _textureId = (await _platform.createWithOptions(creationOptions)) ?? kUninitializedTextureId; _creatingCompleter!.complete(null); final Completer initializingCompleter = Completer(); diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 13db46e3300..611abee9aac 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -33,6 +33,20 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future create(DataSource dataSource) async { + return createWithOptions( + VideoCreationOptions( + dataSource: dataSource, + // Texture view was the only supported view type before + // createWithOptions was introduced. + viewType: VideoViewType.textureView, + ), + ); + } + + @override + Future createWithOptions(VideoCreationOptions options) { + final DataSource dataSource = options.dataSource; + String? asset; String? packageName; String? uri; @@ -51,16 +65,16 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { case DataSourceType.contentUri: uri = dataSource.uri; } - final CreationOptions options = CreationOptions( + final CreationOptions pigeonCreationOptions = CreationOptions( asset: asset, packageName: packageName, uri: uri, httpHeaders: httpHeaders, formatHint: formatHint, - viewType: _platformVideoViewTypeFromVideoViewType(dataSource.viewType), + viewType: _platformVideoViewTypeFromVideoViewType(options.viewType), ); - return _api.create(options); + return _api.create(pigeonCreationOptions); } @override diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index da848cdc306..8ef10f1665c 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -188,23 +188,121 @@ void main() { expect(textureId, 3); }); - test('create with texture view', () async { - final int? textureId = await player.create(DataSource( - sourceType: DataSourceType.file, - uri: 'someUri', - // Texture view is a default view type. - )); + test('createWithOptions with asset', () async { + final int? textureId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.asset, + asset: 'someAsset', + package: 'somePackage', + ), + viewType: VideoViewType.textureView, + ), + ); + expect(log.log.last, 'create'); + expect(log.creationOptions?.asset, 'someAsset'); + expect(log.creationOptions?.packageName, 'somePackage'); + expect(textureId, 3); + }); + + test('createWithOptions with incorrect asset throws exception', () async { + try { + await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.asset, + asset: '/path/to/incorrect_asset', + ), + viewType: VideoViewType.textureView, + ), + ); + fail('should throw PlatformException'); + } catch (e) { + expect(e, isException); + } + }); + + test('createWithOptions with network', () async { + final int? textureId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.network, + uri: 'someUri', + formatHint: VideoFormat.dash, + ), + viewType: VideoViewType.textureView, + ), + ); + expect(log.log.last, 'create'); + expect(log.creationOptions?.asset, null); + expect(log.creationOptions?.uri, 'someUri'); + expect(log.creationOptions?.packageName, null); + expect(log.creationOptions?.formatHint, 'dash'); + expect(log.creationOptions?.httpHeaders, {}); + expect(textureId, 3); + }); + + test('createWithOptions with network (some headers)', () async { + final int? textureId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.network, + uri: 'someUri', + httpHeaders: {'Authorization': 'Bearer token'}, + ), + viewType: VideoViewType.textureView, + ), + ); + expect(log.log.last, 'create'); + expect(log.creationOptions?.asset, null); + expect(log.creationOptions?.uri, 'someUri'); + expect(log.creationOptions?.packageName, null); + expect(log.creationOptions?.formatHint, null); + expect(log.creationOptions?.httpHeaders, + {'Authorization': 'Bearer token'}); + expect(textureId, 3); + }); + + test('createWithOptions with file', () async { + final int? textureId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + ), + viewType: VideoViewType.textureView, + ), + ); + expect(log.log.last, 'create'); + expect(log.creationOptions?.uri, 'someUri'); + expect(textureId, 3); + }); + + test('createWithOptions with texture view', () async { + final int? textureId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + ), + viewType: VideoViewType.textureView, + ), + ); expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); expect(textureId, 3); }); - test('create with platform view', () async { - final int? playerId = await player.create(DataSource( - sourceType: DataSourceType.file, - uri: 'someUri', - viewType: VideoViewType.platformView, - )); + test('createWithOptions with platform view', () async { + final int? playerId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + ), + viewType: VideoViewType.platformView, + ), + ); expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.platformView); expect(playerId, 3); diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index f0a696c494b..8dd23fe3a6a 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -49,11 +49,18 @@ abstract class VideoPlayerPlatform extends PlatformInterface { } /// Creates an instance of a video player and returns its playerId. - /// If view type is [VideoViewType.textureView], the playerId is also the texture id. + @Deprecated('Use createWithOptions() instead.') Future create(DataSource dataSource) { throw UnimplementedError('create() has not been implemented.'); } + /// Creates an instance of a video player based on creation options + /// and returns its playerId. If view type is [VideoViewType.textureView], + /// the playerId is also the texture id. + Future createWithOptions(VideoCreationOptions options) { + return create(options.dataSource); + } + /// Returns a Stream of [VideoEventType]s. Stream videoEventsFor(int textureId) { throw UnimplementedError('videoEventsFor() has not been implemented.'); @@ -143,7 +150,6 @@ class DataSource { this.asset, this.package, this.httpHeaders = const {}, - this.viewType = VideoViewType.textureView, }); /// The way in which the video was originally loaded. @@ -173,9 +179,6 @@ class DataSource { /// The package that the asset was loaded from. Only set for /// [DataSourceType.asset] videos. final String? package; - - /// The type of view to be used for displaying the video player. - final VideoViewType viewType; } /// The way in which the video was originally loaded. @@ -514,3 +517,19 @@ class VideoViewOptions { /// The type of the video view. final VideoViewType viewType; } + +/// [VideoViewOptions] contains creation options for a video player. +@immutable +class VideoCreationOptions { + /// Constructs an instance of [VideoCreationOptions]. + const VideoCreationOptions({ + required this.dataSource, + required this.viewType, + }); + + /// The data source used to create the player. + final DataSource dataSource; + + /// The type of view to be used for displaying the video player + final VideoViewType viewType; +} From fe409ed2febfff4bd0d4eee93b160b5d1ec95f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 17:13:16 +0100 Subject: [PATCH 115/167] Add a todo --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 1 + 1 file changed, 1 insertion(+) 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 686b20f8035..3723502364a 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 @@ -39,6 +39,7 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr #pragma mark - +// TODO(stuartmorgan): Decouple IDs for platform views and texture views. /// The next non-texture player ID, initialized to a high number to avoid collisions with /// texture IDs (which are generated separately). static int64_t nextNonTexturePlayerId = INT_MAX; From 057285f8a9c09c05812d67dfe1393e07dfe8c6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 7 Jan 2025 17:19:26 +0100 Subject: [PATCH 116/167] Fix dartdoc --- .../lib/video_player_platform_interface.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 8dd23fe3a6a..a98b5c270ca 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -518,7 +518,7 @@ class VideoViewOptions { final VideoViewType viewType; } -/// [VideoViewOptions] contains creation options for a video player. +/// [VideoCreationOptions] contains creation options for a video player. @immutable class VideoCreationOptions { /// Constructs an instance of [VideoCreationOptions]. From 3610b348002cfa424b346f29a7e0e7baf93d6ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 10:39:28 +0100 Subject: [PATCH 117/167] Remove - unnecessary casts --- .../FVPTextureBasedVideoPlayer.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 5b26785f921..2a1282532d2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -32,8 +32,8 @@ - (instancetype)initWithAsset:(NSString *)asset } #endif return [self initWithURL:[NSURL fileURLWithPath:path] - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink + frameUpdater:frameUpdater + displayLink:displayLink httpHeaders:@{} avFactory:avFactory registrar:registrar]; @@ -52,8 +52,8 @@ - (instancetype)initWithURL:(NSURL *)url AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:options]; AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:urlAsset]; return [self initWithPlayerItem:item - frameUpdater:(FVPFrameUpdater *)frameUpdater - displayLink:(FVPDisplayLink *)displayLink + frameUpdater:frameUpdater + displayLink:displayLink avFactory:avFactory registrar:registrar]; } From 93ec315c7d435b402b2fb2600550e8db65c776f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 10:56:19 +0100 Subject: [PATCH 118/167] Convert static variable to an ivar --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 3723502364a..c879f931ed5 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 @@ -39,17 +39,14 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr #pragma mark - -// TODO(stuartmorgan): Decouple IDs for platform views and texture views. -/// The next non-texture player ID, initialized to a high number to avoid collisions with -/// texture IDs (which are generated separately). -static int64_t nextNonTexturePlayerId = INT_MAX; - @interface FVPVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject *registry; @property(readonly, weak, nonatomic) NSObject *messenger; @property(readonly, strong, nonatomic) NSObject *registrar; @property(nonatomic, strong) id displayLinkFactory; @property(nonatomic, strong) id avFactory; +// TODO(stuartmorgan): Decouple IDs for platform views and texture views. +@property(nonatomic, assign) int64_t nextNonTexturePlayerId; @end @implementation FVPVideoPlayerPlugin @@ -85,6 +82,9 @@ - (instancetype)initWithAVFactory:(id)avFactory _displayLinkFactory = displayLinkFactory ?: [[FVPDefaultDisplayLinkFactory alloc] init]; _avFactory = avFactory ?: [[FVPDefaultAVFactory alloc] init]; _playersById = [NSMutableDictionary dictionaryWithCapacity:1]; + // Initialized to a high number to avoid collisions with texture IDs (which are generated + // separately). + _nextNonTexturePlayerId = INT_MAX; return self; } @@ -102,7 +102,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; frameUpdater.textureId = playerId; } else { - playerId = nextNonTexturePlayerId--; + playerId = self.nextNonTexturePlayerId--; } FlutterEventChannel *eventChannel = [FlutterEventChannel From 551e2b13d1d50ee3be0db4401ec2482d5c1d04a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 10:56:59 +0100 Subject: [PATCH 119/167] Add missing newline at the end of file --- .../video_player_avfoundation_ios/FVPNativeVideoViewFactory.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_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 050bf48e932..f5864c97a47 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -35,4 +35,4 @@ - (instancetype)initWithMessenger:(NSObject *)messenger return FVPGetMessagesCodec(); } -@end \ No newline at end of file +@end From 9fbc43d12c32f8caa052f0925c449f1d6e965a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 11:16:15 +0100 Subject: [PATCH 120/167] Use private properties instead of ivars --- .../FVPNativeVideoView.m | 13 +++++++------ .../FVPNativeVideoViewFactory.m | 12 +++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m index 4e29fe86008..f00791582e9 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoView.m @@ -19,19 +19,20 @@ - (void)setPlayer:(AVPlayer *)player { } @end -@implementation FVPNativeVideoView { - FVPPlayerView *_view; -} +@interface FVPNativeVideoView () +@property(nonatomic) FVPPlayerView *playerView; +@end +@implementation FVPNativeVideoView - (instancetype)initWithPlayer:(AVPlayer *)player { if (self = [super init]) { - _view = [[FVPPlayerView alloc] init]; - [_view setPlayer:player]; + _playerView = [[FVPPlayerView alloc] init]; + [_playerView setPlayer:player]; } return self; } - (FVPPlayerView *)view { - return _view; + return self.playerView; } @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index f5864c97a47..674c2fed346 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -8,10 +8,12 @@ #import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" #import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" -@implementation FVPNativeVideoViewFactory { - NSObject *_messenger; - FVPVideoPlayer * (^_playerByIdProvider)(NSNumber *); -} +@interface FVPNativeVideoViewFactory () +@property(nonatomic, strong) NSObject *messenger; +@property(nonatomic, copy) FVPVideoPlayer * (^playerByIdProvider)(NSNumber *); +@end + +@implementation FVPNativeVideoViewFactory - (instancetype)initWithMessenger:(NSObject *)messenger playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { @@ -27,7 +29,7 @@ - (instancetype)initWithMessenger:(NSObject *)messenger viewIdentifier:(int64_t)viewId arguments:(FVPPlatformVideoViewCreationParams *)args { NSNumber *playerId = @(args.playerId); - FVPVideoPlayer *player = _playerByIdProvider(playerId); + FVPVideoPlayer *player = self.playerByIdProvider(playerId); return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; } From 2c1f5c4fc8a4373a61553395c406971493abf0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 11:30:56 +0100 Subject: [PATCH 121/167] Fix textureBased condition --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 3 +-- 1 file changed, 1 insertion(+), 2 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 c879f931ed5..7279dc9962e 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 @@ -95,8 +95,7 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { - BOOL textureBased = - frameUpdater != nil && [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; + BOOL textureBased = [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; int64_t playerId; if (textureBased) { playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; From f78d7dae349d9b988d08951a14ed286bd5997421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 14:40:58 +0100 Subject: [PATCH 122/167] Reuse common code in seekTo method --- .../FVPTextureBasedVideoPlayer.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/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 2a1282532d2..50c8a03efb1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -90,30 +90,22 @@ - (void)updatePlayingState { - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHandler { CMTime previousCMTime = self.player.currentTime; - CMTime targetCMTime = CMTimeMake(location, 1000); - CMTimeValue duration = self.player.currentItem.asset.duration.value; - // Without adding tolerance when seeking to duration, - // seekToTime will never complete, and this call will hang. - // see issue https://github.com/flutter/flutter/issues/124475. - CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero; - [self.player seekToTime:targetCMTime - toleranceBefore:tolerance - toleranceAfter:tolerance - completionHandler:^(BOOL completed) { - if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { - // Ensure that a frame is drawn once available, even if currently paused. In theory a - // race is possible here where the new frame has already drawn by the time this code - // runs, and the display link stays on indefinitely, but that should be relatively - // harmless. This must use the display link rather than just informing the engine that a - // new frame is available because the seek completing doesn't guarantee that the pixel - // buffer is already available. - [self expectFrame]; - } - - if (completionHandler) { - completionHandler(completed); - } - }]; + [super seekTo:location + completionHandler:^(BOOL completed) { + if (CMTimeCompare(self.player.currentTime, previousCMTime) != 0) { + // Ensure that a frame is drawn once available, even if currently paused. In theory a + // race is possible here where the new frame has already drawn by the time this code + // runs, and the display link stays on indefinitely, but that should be relatively + // harmless. This must use the display link rather than just informing the engine that a + // new frame is available because the seek completing doesn't guarantee that the pixel + // buffer is already available. + [self expectFrame]; + } + + if (completionHandler) { + completionHandler(completed); + } + }]; } - (void)expectFrame { From 65b26149ae8b8b779c5bf7aee1920aab9fa55707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 10 Jan 2025 16:22:09 +0100 Subject: [PATCH 123/167] Add pragma sections to texture-based video player file --- .../FVPTextureBasedVideoPlayer.m | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 50c8a03efb1..a587793507c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -81,6 +81,30 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item return self; } +- (void)expectFrame { + self.waitingForFrame = YES; + + _displayLink.running = YES; +} + +#pragma mark - Private methods + +- (CALayer *)flutterViewLayer { +#if TARGET_OS_OSX + return self.registrar.view.layer; +#else +#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 + UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; +#pragma clang diagnostic pop + return root.view.layer; +#endif +} + +#pragma mark - Overrides + - (void)updatePlayingState { [super updatePlayingState]; // If the texture is still waiting for an expected frame, the display link needs to keep @@ -108,12 +132,16 @@ - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHan }]; } -- (void)expectFrame { - self.waitingForFrame = YES; +- (void)disposeSansEventChannel { + [super disposeSansEventChannel]; - _displayLink.running = YES; + [self.playerLayer removeFromSuperlayer]; + + _displayLink = nil; } +#pragma mark - FlutterTexture + - (CVPixelBufferRef)copyPixelBuffer { CVPixelBufferRef buffer = NULL; CMTime outputItemTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; @@ -147,26 +175,4 @@ - (void)onTextureUnregistered:(NSObject *)texture { }); } -- (void)disposeSansEventChannel { - [super disposeSansEventChannel]; - - [self.playerLayer removeFromSuperlayer]; - - _displayLink = nil; -} - -- (CALayer *)flutterViewLayer { -#if TARGET_OS_OSX - return self.registrar.view.layer; -#else -#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 - UIViewController *root = UIApplication.sharedApplication.keyWindow.rootViewController; -#pragma clang diagnostic pop - return root.view.layer; -#endif -} - @end From 2915badfa677a953dfeeeee824746b54373e38f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 15 Jan 2025 17:52:03 +0100 Subject: [PATCH 124/167] Simplfy platform interface, do not expose internal details about player id --- .../lib/video_player_platform_interface.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index a98b5c270ca..5b3bd427fbf 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -55,8 +55,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { } /// Creates an instance of a video player based on creation options - /// and returns its playerId. If view type is [VideoViewType.textureView], - /// the playerId is also the texture id. + /// and returns its playerId. Future createWithOptions(VideoCreationOptions options) { return create(options.dataSource); } @@ -508,14 +507,10 @@ class VideoViewOptions { /// Constructs an instance of [VideoViewOptions]. const VideoViewOptions({ required this.playerId, - required this.viewType, }); /// The identifier of the video player. final int playerId; - - /// The type of the video view. - final VideoViewType viewType; } /// [VideoCreationOptions] contains creation options for a video player. From af1d7ebe694dd004713fa05c529636e6ba384557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 15 Jan 2025 17:53:35 +0100 Subject: [PATCH 125/167] Adjust iOS implementation to the new platform interface --- .../lib/src/avfoundation_video_player.dart | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 611abee9aac..546f74a5960 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -15,6 +15,10 @@ import 'messages.g.dart'; class AVFoundationVideoPlayer extends VideoPlayerPlatform { final AVFoundationVideoPlayerApi _api = AVFoundationVideoPlayerApi(); + /// A map that associates player ID with a view type. + /// This is used to determine which view type to use when building a view. + final Map _playerViewTypes = {}; + /// Registers this class as the default instance of [VideoPlayerPlatform]. static void registerWith() { VideoPlayerPlatform.instance = AVFoundationVideoPlayer(); @@ -27,8 +31,9 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { // TODO(FirentisTFW): Rename textureId to playerId everywhere. @override - Future dispose(int textureId) { - return _api.dispose(textureId); + Future dispose(int textureId) async { + await _api.dispose(textureId); + _playerViewTypes.remove(textureId); } @override @@ -44,7 +49,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Future createWithOptions(VideoCreationOptions options) { + Future createWithOptions(VideoCreationOptions options) async { final DataSource dataSource = options.dataSource; String? asset; @@ -74,7 +79,10 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { viewType: _platformVideoViewTypeFromVideoViewType(options.viewType), ); - return _api.create(pigeonCreationOptions); + final int playerId = await _api.create(pigeonCreationOptions); + _playerViewTypes[playerId] = options.viewType; + + return playerId; } @override @@ -163,28 +171,29 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Widget buildView(int textureId) { return buildViewWithOptions( - VideoViewOptions( - playerId: textureId, - // Texture view was the only supported view type before - // buildViewWithOptions was introduced. - viewType: VideoViewType.textureView, - ), + VideoViewOptions(playerId: textureId), ); } @override Widget buildViewWithOptions(VideoViewOptions options) { final int playerId = options.playerId; + final VideoViewType? viewType = _playerViewTypes[playerId]; - return switch (options.viewType) { + return switch (viewType) { + // playerId is also the textureId when using texture view. VideoViewType.textureView => Texture(textureId: playerId), VideoViewType.platformView => _buildPlatformView(playerId), + null => throw Exception( + 'Could not find corresponding view type for playerId: $playerId', + ), }; } Widget _buildPlatformView(int playerId) { final PlatformVideoViewCreationParams creationParams = PlatformVideoViewCreationParams(playerId: playerId); + return IgnorePointer( // IgnorePointer so that GestureDetector can be used above the platform view. child: UiKitView( From 9453edc5b68ba85d721cb9ca603cbfec52ff413c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 15 Jan 2025 17:54:18 +0100 Subject: [PATCH 126/167] Adjust example app's controller to the new platform interface --- .../example/lib/mini_controller.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index 58898bc731d..ee5c0e301ff 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -438,10 +438,7 @@ class _VideoPlayerState extends State { return _textureId == MiniController.kUninitializedTextureId ? Container() : _platform.buildViewWithOptions( - VideoViewOptions( - playerId: _textureId, - viewType: widget.controller.viewType, - ), + VideoViewOptions(playerId: _textureId), ); } } From 37c8dab847e107ebcabcfa4a23942b742b8bec1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 15 Jan 2025 18:25:42 +0100 Subject: [PATCH 127/167] Test playerViewTypes in iOS implementation --- .../lib/src/avfoundation_video_player.dart | 9 +++++---- .../test/avfoundation_video_player_test.dart | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 546f74a5960..a673af011a8 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -17,7 +17,8 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { /// A map that associates player ID with a view type. /// This is used to determine which view type to use when building a view. - final Map _playerViewTypes = {}; + @visibleForTesting + final Map playerViewTypes = {}; /// Registers this class as the default instance of [VideoPlayerPlatform]. static void registerWith() { @@ -33,7 +34,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future dispose(int textureId) async { await _api.dispose(textureId); - _playerViewTypes.remove(textureId); + playerViewTypes.remove(textureId); } @override @@ -80,7 +81,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { ); final int playerId = await _api.create(pigeonCreationOptions); - _playerViewTypes[playerId] = options.viewType; + playerViewTypes[playerId] = options.viewType; return playerId; } @@ -178,7 +179,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Widget buildViewWithOptions(VideoViewOptions options) { final int playerId = options.playerId; - final VideoViewType? viewType = _playerViewTypes[playerId]; + final VideoViewType? viewType = playerViewTypes[playerId]; return switch (viewType) { // playerId is also the textureId when using texture view. diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index 8ef10f1665c..f4c210e1c91 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -118,9 +118,12 @@ void main() { }); test('dispose', () async { + player.playerViewTypes[1] = VideoViewType.textureView; + await player.dispose(1); expect(log.log.last, 'dispose'); expect(log.textureId, 1); + expect(player.playerViewTypes, isEmpty); }); test('create with asset', () async { @@ -133,8 +136,10 @@ void main() { expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); + // FIXME Is this test valid? test('create with incorrect asset throws exception', () async { try { await player.create(DataSource( @@ -160,6 +165,7 @@ void main() { expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('create with network (some headers)', () async { @@ -176,6 +182,7 @@ void main() { expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('create with file', () async { @@ -186,6 +193,7 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('createWithOptions with asset', () async { @@ -203,8 +211,10 @@ void main() { expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); + // FIXME Is this test valid? test('createWithOptions with incorrect asset throws exception', () async { try { await player.createWithOptions( @@ -240,6 +250,7 @@ void main() { expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('createWithOptions with network (some headers)', () async { @@ -261,6 +272,7 @@ void main() { expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('createWithOptions with file', () async { @@ -276,6 +288,7 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('createWithOptions with texture view', () async { @@ -291,6 +304,7 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); expect(textureId, 3); + expect(player.playerViewTypes[3], VideoViewType.textureView); }); test('createWithOptions with platform view', () async { @@ -306,6 +320,7 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.platformView); expect(playerId, 3); + expect(player.playerViewTypes[3], VideoViewType.platformView); }); test('setLooping', () async { From 0045c27f0fcf7fe563f74da5c1c97baec2e5dd65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 15 Jan 2025 18:58:31 +0100 Subject: [PATCH 128/167] Adjust new test's setup after merging main --- .../darwin/RunnerTests/VideoPlayerTests.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 4a8ca14aae3..f7756bc7514 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -945,9 +945,10 @@ - (void)testUpdatePlayingStateShouldNotResetRate { uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4" packageName:nil formatHint:nil - httpHeaders:@{}]; + httpHeaders:@{} + viewType:FVPPlatformVideoViewTypeTextureView]; NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersByTextureId[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; [player onListenWithArguments:nil From bdd5fd3544c2cc7be06bb132995d68e86648dcca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 20 Jan 2025 22:19:19 +0100 Subject: [PATCH 129/167] Introduce VideoPlayerViewState class --- .../lib/src/avfoundation_video_player.dart | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index a673af011a8..e3628734a05 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -15,10 +15,11 @@ import 'messages.g.dart'; class AVFoundationVideoPlayer extends VideoPlayerPlatform { final AVFoundationVideoPlayerApi _api = AVFoundationVideoPlayerApi(); - /// A map that associates player ID with a view type. + /// A map that associates player ID with a view state. /// This is used to determine which view type to use when building a view. @visibleForTesting - final Map playerViewTypes = {}; + final Map playerViewStates = + {}; /// Registers this class as the default instance of [VideoPlayerPlatform]. static void registerWith() { @@ -34,7 +35,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future dispose(int textureId) async { await _api.dispose(textureId); - playerViewTypes.remove(textureId); + playerViewStates.remove(textureId); } @override @@ -81,7 +82,12 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { ); final int playerId = await _api.create(pigeonCreationOptions); - playerViewTypes[playerId] = options.viewType; + playerViewStates[playerId] = switch (options.viewType) { + // playerId is also the textureId when using texture view. + VideoViewType.textureView => + VideoPlayerTextureViewState(textureId: playerId), + VideoViewType.platformView => const VideoPlayerPlatformViewState(), + }; return playerId; } @@ -179,12 +185,12 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Widget buildViewWithOptions(VideoViewOptions options) { final int playerId = options.playerId; - final VideoViewType? viewType = playerViewTypes[playerId]; + final VideoPlayerViewState? viewType = playerViewStates[playerId]; return switch (viewType) { - // playerId is also the textureId when using texture view. - VideoViewType.textureView => Texture(textureId: playerId), - VideoViewType.platformView => _buildPlatformView(playerId), + VideoPlayerTextureViewState(:final int textureId) => + Texture(textureId: textureId), + VideoPlayerPlatformViewState() => _buildPlatformView(playerId), null => throw Exception( 'Could not find corresponding view type for playerId: $playerId', ), @@ -234,3 +240,38 @@ PlatformVideoViewType _platformVideoViewTypeFromVideoViewType( VideoViewType.platformView => PlatformVideoViewType.platformView, }; } + +/// Base class representing the state of a video player view. +@visibleForTesting +@immutable +sealed class VideoPlayerViewState { + const VideoPlayerViewState(); +} + +/// Represents the state of a video player view that uses a texture. +@visibleForTesting +final class VideoPlayerTextureViewState extends VideoPlayerViewState { + /// Creates a new instance of [VideoPlayerTextureViewState]. + const VideoPlayerTextureViewState({ + required this.textureId, + }); + + /// The ID of the texture used by the video player. + final int textureId; + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is VideoPlayerTextureViewState && other.textureId == textureId; + } + + @override + int get hashCode => textureId.hashCode; +} + +/// Represents the state of a video player view that uses a platform view. +@visibleForTesting +final class VideoPlayerPlatformViewState extends VideoPlayerViewState { + /// Creates a new instance of [VideoPlayerPlatformViewState]. + const VideoPlayerPlatformViewState(); +} From cee36ce80177295eb45af232ba364a289bd2d1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 20 Jan 2025 22:19:58 +0100 Subject: [PATCH 130/167] Adjust unit tests to the new type --- .../test/avfoundation_video_player_test.dart | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index f4c210e1c91..e898956f9aa 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -118,12 +118,13 @@ void main() { }); test('dispose', () async { - player.playerViewTypes[1] = VideoViewType.textureView; + player.playerViewStates[1] = + const VideoPlayerTextureViewState(textureId: 1); await player.dispose(1); expect(log.log.last, 'dispose'); expect(log.textureId, 1); - expect(player.playerViewTypes, isEmpty); + expect(player.playerViewStates, isEmpty); }); test('create with asset', () async { @@ -136,7 +137,8 @@ void main() { expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); // FIXME Is this test valid? @@ -165,7 +167,8 @@ void main() { expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('create with network (some headers)', () async { @@ -182,7 +185,8 @@ void main() { expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('create with file', () async { @@ -193,7 +197,8 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with asset', () async { @@ -211,7 +216,8 @@ void main() { expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); // FIXME Is this test valid? @@ -250,7 +256,8 @@ void main() { expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with network (some headers)', () async { @@ -272,7 +279,8 @@ void main() { expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with file', () async { @@ -288,23 +296,8 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); - }); - - test('createWithOptions with texture view', () async { - final int? textureId = await player.createWithOptions( - VideoCreationOptions( - dataSource: DataSource( - sourceType: DataSourceType.file, - uri: 'someUri', - ), - viewType: VideoViewType.textureView, - ), - ); - expect(log.log.last, 'create'); - expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); - expect(textureId, 3); - expect(player.playerViewTypes[3], VideoViewType.textureView); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with platform view', () async { @@ -320,7 +313,7 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.viewType, PlatformVideoViewType.platformView); expect(playerId, 3); - expect(player.playerViewTypes[3], VideoViewType.platformView); + expect(player.playerViewStates[3], const VideoPlayerPlatformViewState()); }); test('setLooping', () async { From 09e148e477f578c5fd6e030ecb99c7e2745a669b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 20 Jan 2025 23:00:31 +0100 Subject: [PATCH 131/167] Move throw-exception-on-invalid-asset test from Dart side to native iOS side --- .../darwin/RunnerTests/VideoPlayerTests.m | 26 ++++++++++++++++ .../test/avfoundation_video_player_test.dart | 31 ------------------- 2 files changed, 26 insertions(+), 31 deletions(-) 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 f7756bc7514..91ded6527dd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -165,6 +165,32 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id)registr @implementation VideoPlayerTests +- (void)testCreateWithOptionsReturnsErrorForInvalidAssetPath { + NSObject *registrar = [GetPluginRegistry() + registrarForPlugin:@"testCreateWithOptionsReturnsErrorForInvalidAssetPath"]; + FVPVideoPlayerPlugin *videoPlayerPlugin = + [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; + + FlutterError *initializationError; + [videoPlayerPlugin initialize:&initializationError]; + XCTAssertNil(initializationError); + + FVPCreationOptions *create = + [FVPCreationOptions makeWithAsset:@"invalid/path/to/asset" + uri:nil + packageName:nil + formatHint:nil + httpHeaders:@{} + viewType:FVPPlatformVideoViewTypeTextureView]; + + FlutterError *createError; + NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + + XCTAssertNil(textureId); + XCTAssertNotNil(createError); + XCTAssertEqualObjects(createError.code, @"video_player"); +} + - (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 diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index e898956f9aa..6c3855c0df8 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -141,19 +141,6 @@ void main() { const VideoPlayerTextureViewState(textureId: 3)); }); - // FIXME Is this test valid? - test('create with incorrect asset throws exception', () async { - try { - await player.create(DataSource( - sourceType: DataSourceType.asset, - asset: '/path/to/incorrect_asset', - )); - fail('should throw PlatformException'); - } catch (e) { - expect(e, isException); - } - }); - test('create with network', () async { final int? textureId = await player.create(DataSource( sourceType: DataSourceType.network, @@ -220,24 +207,6 @@ void main() { const VideoPlayerTextureViewState(textureId: 3)); }); - // FIXME Is this test valid? - test('createWithOptions with incorrect asset throws exception', () async { - try { - await player.createWithOptions( - VideoCreationOptions( - dataSource: DataSource( - sourceType: DataSourceType.asset, - asset: '/path/to/incorrect_asset', - ), - viewType: VideoViewType.textureView, - ), - ); - fail('should throw PlatformException'); - } catch (e) { - expect(e, isException); - } - }); - test('createWithOptions with network', () async { final int? textureId = await player.createWithOptions( VideoCreationOptions( From cca3655a4a935b23bbaf6a515ae7584b55b2ce3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 20 Jan 2025 23:03:22 +0100 Subject: [PATCH 132/167] Rename variable --- .../lib/src/avfoundation_video_player.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index e3628734a05..bf37d556945 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -185,9 +185,9 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Widget buildViewWithOptions(VideoViewOptions options) { final int playerId = options.playerId; - final VideoPlayerViewState? viewType = playerViewStates[playerId]; + final VideoPlayerViewState? viewState = playerViewStates[playerId]; - return switch (viewType) { + return switch (viewState) { VideoPlayerTextureViewState(:final int textureId) => Texture(textureId: textureId), VideoPlayerPlatformViewState() => _buildPlatformView(playerId), @@ -260,10 +260,9 @@ final class VideoPlayerTextureViewState extends VideoPlayerViewState { final int textureId; @override - bool operator ==(Object other) { - return identical(this, other) || - other is VideoPlayerTextureViewState && other.textureId == textureId; - } + bool operator ==(Object other) => + identical(this, other) || + other is VideoPlayerTextureViewState && other.textureId == textureId; @override int get hashCode => textureId.hashCode; From af79cc0e40f71106f09345f8afd0f5e329ce3c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Mon, 20 Jan 2025 23:38:45 +0100 Subject: [PATCH 133/167] Mock lookupKeyForAsset method --- .../darwin/RunnerTests/VideoPlayerTests.m | 3 +++ 1 file changed, 3 insertions(+) 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 91ded6527dd..b993f76c5dd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -175,6 +175,9 @@ - (void)testCreateWithOptionsReturnsErrorForInvalidAssetPath { [videoPlayerPlugin initialize:&initializationError]; XCTAssertNil(initializationError); + id mockRegistrar = OCMPartialMock(registrar); + OCMStub([mockRegistrar lookupKeyForAsset:[OCMArg any]]).andReturn(nil); + FVPCreationOptions *create = [FVPCreationOptions makeWithAsset:@"invalid/path/to/asset" uri:nil From e5c3c9935f1ca504d4294b6b57ee9ae47433d7e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 24 Jan 2025 09:20:28 +0100 Subject: [PATCH 134/167] Pass onDisposed callback to FVPTextureBasedVideoPlayer --- .../FVPTextureBasedVideoPlayer.m | 27 ++++++++++++++----- .../FVPVideoPlayerPlugin.m | 26 +++++++++--------- .../FVPTextureBasedVideoPlayer.h | 6 +++-- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index a587793507c..4ce643041d1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -15,6 +15,7 @@ @interface FVPTextureBasedVideoPlayer () // (e.g., after a seek while paused). If YES, the display link should continue to run until the next // frame is successfully provided. @property(nonatomic, assign) BOOL waitingForFrame; +@property(nonatomic, copy) void (^onDisposed)(int64_t); @end @implementation FVPTextureBasedVideoPlayer @@ -22,7 +23,8 @@ - (instancetype)initWithAsset:(NSString *)asset frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory - registrar:(NSObject *)registrar { + registrar:(NSObject *)registrar + onDisposed:(void (^)(int64_t))onDisposed { NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; #if TARGET_OS_OSX // See https://github.com/flutter/flutter/issues/135302 @@ -36,7 +38,8 @@ - (instancetype)initWithAsset:(NSString *)asset displayLink:displayLink httpHeaders:@{} avFactory:avFactory - registrar:registrar]; + registrar:registrar + onDisposed:onDisposed]; } - (instancetype)initWithURL:(NSURL *)url @@ -44,7 +47,8 @@ - (instancetype)initWithURL:(NSURL *)url displayLink:(FVPDisplayLink *)displayLink httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory - registrar:(NSObject *)registrar { + registrar:(NSObject *)registrar + onDisposed:(void (^)(int64_t))onDisposed { NSDictionary *options = nil; if ([headers count] != 0) { options = @{@"AVURLAssetHTTPHeaderFieldsKey" : headers}; @@ -55,20 +59,23 @@ - (instancetype)initWithURL:(NSURL *)url frameUpdater:frameUpdater displayLink:displayLink avFactory:avFactory - registrar:registrar]; + registrar:registrar + onDisposed:onDisposed]; } - (instancetype)initWithPlayerItem:(AVPlayerItem *)item frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory - registrar:(NSObject *)registrar { + registrar:(NSObject *)registrar + onDisposed:(void (^)(int64_t))onDisposed { self = [super initWithPlayerItem:item avFactory:avFactory registrar:registrar]; if (self) { _frameUpdater = frameUpdater; _displayLink = displayLink; _frameUpdater.videoOutput = self.videoOutput; + _onDisposed = [onDisposed copy]; // 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 @@ -140,6 +147,12 @@ - (void)disposeSansEventChannel { _displayLink = nil; } +- (void)dispose { + [super dispose]; + + _onDisposed(self.frameUpdater.textureId); +} + #pragma mark - FlutterTexture - (CVPixelBufferRef)copyPixelBuffer { @@ -171,7 +184,9 @@ - (CVPixelBufferRef)copyPixelBuffer { - (void)onTextureUnregistered:(NSObject *)texture { dispatch_async(dispatch_get_main_queue(), ^{ - [self dispose]; + if (!self.disposed) { + [self dispose]; + } }); } 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 11b0933a562..987980a0f62 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 @@ -194,11 +194,15 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } @try { if (textureBased) { - player = [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath - frameUpdater:frameUpdater - displayLink:displayLink - avFactory:_avFactory - registrar:self.registrar]; + player = + [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath + frameUpdater:frameUpdater + displayLink:displayLink + avFactory:_avFactory + registrar:self.registrar + onDisposed:^(int64_t textureId) { + [self.registry unregisterTexture:textureId]; + }]; } else { player = [[FVPVideoPlayer alloc] initWithAsset:assetPath avFactory:_avFactory @@ -216,7 +220,10 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options displayLink:displayLink httpHeaders:options.httpHeaders avFactory:_avFactory - registrar:self.registrar]; + registrar:self.registrar + onDisposed:^(int64_t textureId) { + [self.registry unregisterTexture:textureId]; + }]; } else { player = [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] httpHeaders:options.httpHeaders @@ -233,13 +240,8 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options - (void)disposePlayer:(NSInteger)playerId error:(FlutterError **)error { NSNumber *playerKey = @(playerId); FVPVideoPlayer *player = self.playersById[playerKey]; - if ([player isKindOfClass:[FVPTextureBasedVideoPlayer class]]) { - [self.registry unregisterTexture:playerId]; - } [self.playersById removeObjectForKey:playerKey]; - if (!player.disposed) { - [player dispose]; - } + [player dispose]; } - (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)playerId error:(FlutterError **)error { diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index c877420e7e1..efdfe237ecd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -19,7 +19,8 @@ NS_ASSUME_NONNULL_BEGIN displayLink:(FVPDisplayLink *)displayLink httpHeaders:(nonnull NSDictionary *)headers avFactory:(id)avFactory - registrar:(NSObject *)registrar; + registrar:(NSObject *)registrar + onDisposed:(void (^)(int64_t))onDisposed; /// Initializes a new instance of FVPTextureBasedVideoPlayer with the given asset, frame updater, /// display link, AV factory, and registrar. @@ -27,7 +28,8 @@ NS_ASSUME_NONNULL_BEGIN frameUpdater:(FVPFrameUpdater *)frameUpdater displayLink:(FVPDisplayLink *)displayLink avFactory:(id)avFactory - registrar:(NSObject *)registrar; + registrar:(NSObject *)registrar + onDisposed:(void (^)(int64_t))onDisposed; // Tells the player to run its frame updater until it receives a frame, regardless of the // play/pause state. From 70e4215ca7d98b640e0cba665393de8b94ac6190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 24 Jan 2025 10:14:25 +0100 Subject: [PATCH 135/167] Refactor players initialization in plugin file --- .../FVPTextureBasedVideoPlayer.m | 4 + .../FVPVideoPlayerPlugin.m | 127 ++++++++++-------- .../FVPTextureBasedVideoPlayer.h | 8 +- 3 files changed, 82 insertions(+), 57 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 4ce643041d1..a4a3fd34207 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -88,6 +88,10 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item return self; } +- (void)setTextureId:(int64_t)textureId { + self.frameUpdater.textureId = textureId; +} + - (void)expectFrame { self.waitingForFrame = YES; 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 987980a0f62..dad46f91d5b 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 @@ -94,12 +94,12 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, nil); } -- (int64_t)onPlayerSetup:(FVPVideoPlayer *)player frameUpdater:(FVPFrameUpdater *)frameUpdater { +- (int64_t)onPlayerSetup:(FVPVideoPlayer *)player { BOOL textureBased = [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; int64_t playerId; if (textureBased) { playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; - frameUpdater.textureId = playerId; + [(FVPTextureBasedVideoPlayer *)player setTextureId:playerId]; } else { playerId = self.nextNonTexturePlayerId--; } @@ -174,67 +174,84 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options error:(FlutterError **)error { BOOL textureBased = options.viewType == FVPPlatformVideoViewTypeTextureView; - FVPFrameUpdater *frameUpdater; - FVPDisplayLink *displayLink; - if (textureBased) { - frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; - displayLink = [self.displayLinkFactory displayLinkWithRegistrar:_registrar - callback:^() { - [frameUpdater displayLinkFired]; - }]; - } - FVPVideoPlayer *player; - if (options.asset) { - NSString *assetPath; - if (options.packageName) { - assetPath = [_registrar lookupKeyForAsset:options.asset fromPackage:options.packageName]; + @try { + FVPVideoPlayer *player; + if (textureBased) { + player = [self createTextureBasedPlayerFromOptions:options]; } else { - assetPath = [_registrar lookupKeyForAsset:options.asset]; + player = [self createRegularPlayerFromOptions:options]; } - @try { - if (textureBased) { - player = - [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath - frameUpdater:frameUpdater - displayLink:displayLink - avFactory:_avFactory - registrar:self.registrar - onDisposed:^(int64_t textureId) { - [self.registry unregisterTexture:textureId]; - }]; - } else { - player = [[FVPVideoPlayer alloc] initWithAsset:assetPath - avFactory:_avFactory - registrar:self.registrar]; - } - return @([self onPlayerSetup:player frameUpdater:frameUpdater]); - } @catch (NSException *exception) { - *error = [FlutterError errorWithCode:@"video_player" message:exception.reason details:nil]; + + if (player == nil) { + *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; return nil; } + + return @([self onPlayerSetup:player]); + } @catch (NSException *exception) { + *error = [FlutterError errorWithCode:@"video_player" message:exception.reason details:nil]; + return nil; + } +} + +- (nullable NSNumber *)createTextureBasedPlayerFromOptions:(nonnull FVPCreationOptions *)options { + FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; + FVPDisplayLink *displayLink = + [self.displayLinkFactory displayLinkWithRegistrar:_registrar + callback:^() { + [frameUpdater displayLinkFired]; + }]; + + void (^onDisposed)(int64_t) = ^(int64_t textureId) { + [self.registry unregisterTexture:textureId]; + }; + + if (options.asset) { + NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; + return [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath + frameUpdater:frameUpdater + displayLink:displayLink + avFactory:_avFactory + registrar:self.registrar + onDisposed:onDisposed]; } else if (options.uri) { - if (textureBased) { - player = [[FVPTextureBasedVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] - frameUpdater:frameUpdater - displayLink:displayLink - httpHeaders:options.httpHeaders - avFactory:_avFactory - registrar:self.registrar - onDisposed:^(int64_t textureId) { - [self.registry unregisterTexture:textureId]; - }]; - } else { - player = [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] - httpHeaders:options.httpHeaders - avFactory:_avFactory - registrar:self.registrar]; - } - return @([self onPlayerSetup:player frameUpdater:frameUpdater]); + return [[FVPTextureBasedVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] + frameUpdater:frameUpdater + displayLink:displayLink + httpHeaders:options.httpHeaders + avFactory:_avFactory + registrar:self.registrar + onDisposed:onDisposed]; + } + + return nil; +} + +- (nullable NSNumber *)createRegularPlayerFromOptions:(nonnull FVPCreationOptions *)options { + if (options.asset) { + NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; + return [[FVPVideoPlayer alloc] initWithAsset:assetPath + avFactory:_avFactory + registrar:self.registrar]; + } else if (options.uri) { + return [[FVPVideoPlayer alloc] initWithURL:[NSURL URLWithString:options.uri] + httpHeaders:options.httpHeaders + avFactory:_avFactory + registrar:self.registrar]; + } + + return nil; +} + +- (NSString *)prepareAssetPathFromCreationOptions:(nonnull FVPCreationOptions *)options { + NSString *assetPath; + if (options.packageName) { + assetPath = [self.registrar lookupKeyForAsset:options.asset fromPackage:options.packageName]; } else { - *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; - return nil; + assetPath = [self.registrar lookupKeyForAsset:options.asset]; } + return assetPath; } - (void)disposePlayer:(NSInteger)playerId error:(FlutterError **)error { diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index efdfe237ecd..90cfae4633e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -31,8 +31,12 @@ NS_ASSUME_NONNULL_BEGIN registrar:(NSObject *)registrar onDisposed:(void (^)(int64_t))onDisposed; -// Tells the player to run its frame updater until it receives a frame, regardless of the -// play/pause state. +/// Sets the texture ID for the frame updater. This method should be called once the texture ID is +/// obtained from the texture registry. +- (void)setTextureId:(int64_t)textureId; + +/// Tells the player to run its frame updater until it receives a frame, regardless of the +/// play/pause state. - (void)expectFrame; @end From 80fffcf446217ec91e24b9208d69444e082049a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 24 Jan 2025 10:53:18 +0100 Subject: [PATCH 136/167] Fix return type --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 5 +++-- 1 file changed, 3 insertions(+), 2 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 dad46f91d5b..9ad702ccb44 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 @@ -195,7 +195,8 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } -- (nullable NSNumber *)createTextureBasedPlayerFromOptions:(nonnull FVPCreationOptions *)options { +- (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerFromOptions: + (nonnull FVPCreationOptions *)options { FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; FVPDisplayLink *displayLink = [self.displayLinkFactory displayLinkWithRegistrar:_registrar @@ -228,7 +229,7 @@ - (nullable NSNumber *)createTextureBasedPlayerFromOptions:(nonnull FVPCreationO return nil; } -- (nullable NSNumber *)createRegularPlayerFromOptions:(nonnull FVPCreationOptions *)options { +- (nullable FVPVideoPlayer *)createRegularPlayerFromOptions:(nonnull FVPCreationOptions *)options { if (options.asset) { NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; return [[FVPVideoPlayer alloc] initWithAsset:assetPath From 6d236b4c2b4ea6b2c4b189b2ca110790143696ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 10:30:00 +0100 Subject: [PATCH 137/167] Bump platform interface dependency to 6.3.0 --- .../video_player_avfoundation/pubspec.yaml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 57b980f7ef6..9b4bbb6627e 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -24,7 +24,7 @@ flutter: dependencies: flutter: sdk: flutter - video_player_platform_interface: ">=6.1.0 <7.0.0" + video_player_platform_interface: ">=6.3.0 <7.0.0" dev_dependencies: flutter_test: @@ -34,11 +34,3 @@ dev_dependencies: topics: - video - video-player - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { path: ../../../packages/video_player/video_player_platform_interface }, - } From 7cd5f14f014b4b2ac79e8413a2df93695c00a1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 10:32:51 +0100 Subject: [PATCH 138/167] Rename textureId to playerId in platform interace methods --- .../lib/src/avfoundation_video_player.dart | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 7c80dbca2da..91b01c20e4d 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -10,9 +10,6 @@ import 'package:video_player_platform_interface/video_player_platform_interface. import 'messages.g.dart'; -// TODO(FirentisTFW): Remove the ignore and rename parameters when adding support for platform views. -// ignore_for_file: avoid_renaming_method_parameters - /// An iOS implementation of [VideoPlayerPlatform] that uses the /// Pigeon-generated [VideoPlayerApi]. class AVFoundationVideoPlayer extends VideoPlayerPlatform { @@ -34,11 +31,10 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { return _api.initialize(); } - // TODO(FirentisTFW): Rename textureId to playerId everywhere. @override - Future dispose(int textureId) async { - await _api.dispose(textureId); - playerViewStates.remove(textureId); + Future dispose(int playerId) async { + await _api.dispose(playerId); + playerViewStates.remove(playerId); } @override @@ -96,46 +92,46 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Future setLooping(int textureId, bool looping) { - return _api.setLooping(looping, textureId); + Future setLooping(int playerId, bool looping) { + return _api.setLooping(looping, playerId); } @override - Future play(int textureId) { - return _api.play(textureId); + Future play(int playerId) { + return _api.play(playerId); } @override - Future pause(int textureId) { - return _api.pause(textureId); + Future pause(int playerId) { + return _api.pause(playerId); } @override - Future setVolume(int textureId, double volume) { - return _api.setVolume(volume, textureId); + Future setVolume(int playerId, double volume) { + return _api.setVolume(volume, playerId); } @override - Future setPlaybackSpeed(int textureId, double speed) { + Future setPlaybackSpeed(int playerId, double speed) { assert(speed > 0); - return _api.setPlaybackSpeed(speed, textureId); + return _api.setPlaybackSpeed(speed, playerId); } @override - Future seekTo(int textureId, Duration position) { - return _api.seekTo(position.inMilliseconds, textureId); + Future seekTo(int playerId, Duration position) { + return _api.seekTo(position.inMilliseconds, playerId); } @override - Future getPosition(int textureId) async { - final int position = await _api.getPosition(textureId); + Future getPosition(int playerId) async { + final int position = await _api.getPosition(playerId); return Duration(milliseconds: position); } @override - Stream videoEventsFor(int textureId) { - return _eventChannelFor(textureId) + Stream videoEventsFor(int playerId) { + return _eventChannelFor(playerId) .receiveBroadcastStream() .map((dynamic event) { final Map map = event as Map; @@ -179,9 +175,9 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { } @override - Widget buildView(int textureId) { + Widget buildView(int playerId) { return buildViewWithOptions( - VideoViewOptions(playerId: textureId), + VideoViewOptions(playerId: playerId), ); } @@ -214,8 +210,8 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { ); } - EventChannel _eventChannelFor(int textureId) { - return EventChannel('flutter.io/videoPlayer/videoEvents$textureId'); + EventChannel _eventChannelFor(int playerId) { + return EventChannel('flutter.io/videoPlayer/videoEvents$playerId'); } static const Map _videoFormatStringMap = From 3d3b59d6b4acebce3001bbc5666f20c4813e8dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 11:10:21 +0100 Subject: [PATCH 139/167] Rename textureId to playerId in iOS Dart files --- .../example/lib/mini_controller.dart | 48 +++++------ .../lib/src/messages.g.dart | 32 ++++---- .../pigeons/messages.dart | 16 ++-- .../test/avfoundation_video_player_test.dart | 82 +++++++++---------- .../test/test_api.g.dart | 64 +++++++-------- 5 files changed, 121 insertions(+), 121 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart index ee5c0e301ff..7d406ecbd1a 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart @@ -210,15 +210,15 @@ class MiniController extends ValueNotifier { Completer? _creatingCompleter; StreamSubscription? _eventSubscription; - /// The id of a texture that hasn't been initialized. + /// The id of a player that hasn't been initialized. @visibleForTesting - static const int kUninitializedTextureId = -1; - int _textureId = kUninitializedTextureId; + static const int kUninitializedPlayerId = -1; + int _playerId = kUninitializedPlayerId; /// This is just exposed for testing. It shouldn't be used by anyone depending /// on the plugin. @visibleForTesting - int get textureId => _textureId; + int get playerId => _playerId; /// Attempts to open the given [dataSource] and load metadata about the video. Future initialize() async { @@ -254,8 +254,8 @@ class MiniController extends ValueNotifier { viewType: viewType, ); - _textureId = (await _platform.createWithOptions(creationOptions)) ?? - kUninitializedTextureId; + _playerId = (await _platform.createWithOptions(creationOptions)) ?? + kUninitializedPlayerId; _creatingCompleter!.complete(null); final Completer initializingCompleter = Completer(); @@ -268,8 +268,8 @@ class MiniController extends ValueNotifier { isInitialized: event.duration != null, ); initializingCompleter.complete(null); - _platform.setVolume(_textureId, 1.0); - _platform.setLooping(_textureId, true); + _platform.setVolume(_playerId, 1.0); + _platform.setLooping(_playerId, true); _applyPlayPause(); case VideoEventType.completed: pause().then((void pauseResult) => seekTo(value.duration)); @@ -296,7 +296,7 @@ class MiniController extends ValueNotifier { } _eventSubscription = _platform - .videoEventsFor(_textureId) + .videoEventsFor(_playerId) .listen(eventListener, onError: errorListener); return initializingCompleter.future; } @@ -307,7 +307,7 @@ class MiniController extends ValueNotifier { await _creatingCompleter!.future; _timer?.cancel(); await _eventSubscription?.cancel(); - await _platform.dispose(_textureId); + await _platform.dispose(_playerId); } super.dispose(); } @@ -327,7 +327,7 @@ class MiniController extends ValueNotifier { Future _applyPlayPause() async { _timer?.cancel(); if (value.isPlaying) { - await _platform.play(_textureId); + await _platform.play(_playerId); _timer = Timer.periodic( const Duration(milliseconds: 500), @@ -341,14 +341,14 @@ class MiniController extends ValueNotifier { ); await _applyPlaybackSpeed(); } else { - await _platform.pause(_textureId); + await _platform.pause(_playerId); } } Future _applyPlaybackSpeed() async { if (value.isPlaying) { await _platform.setPlaybackSpeed( - _textureId, + _playerId, value.playbackSpeed, ); } @@ -356,7 +356,7 @@ class MiniController extends ValueNotifier { /// The position in the current video. Future get position async { - return _platform.getPosition(_textureId); + return _platform.getPosition(_playerId); } /// Sets the video's current timestamp to be at [position]. @@ -366,7 +366,7 @@ class MiniController extends ValueNotifier { } else if (position < Duration.zero) { position = Duration.zero; } - await _platform.seekTo(_textureId, position); + await _platform.seekTo(_playerId, position); _updatePosition(position); } @@ -397,10 +397,10 @@ class VideoPlayer extends StatefulWidget { class _VideoPlayerState extends State { _VideoPlayerState() { _listener = () { - final int newTextureId = widget.controller.textureId; - if (newTextureId != _textureId) { + final int newPlayerId = widget.controller.playerId; + if (newPlayerId != _playerId) { setState(() { - _textureId = newTextureId; + _playerId = newPlayerId; }); } }; @@ -408,13 +408,13 @@ class _VideoPlayerState extends State { late VoidCallback _listener; - late int _textureId; + late int _playerId; @override void initState() { super.initState(); - _textureId = widget.controller.textureId; - // Need to listen for initialization events since the actual texture ID + _playerId = widget.controller.playerId; + // Need to listen for initialization events since the actual player ID // becomes available after asynchronous initialization finishes. widget.controller.addListener(_listener); } @@ -423,7 +423,7 @@ class _VideoPlayerState extends State { void didUpdateWidget(VideoPlayer oldWidget) { super.didUpdateWidget(oldWidget); oldWidget.controller.removeListener(_listener); - _textureId = widget.controller.textureId; + _playerId = widget.controller.playerId; widget.controller.addListener(_listener); } @@ -435,10 +435,10 @@ class _VideoPlayerState extends State { @override Widget build(BuildContext context) { - return _textureId == MiniController.kUninitializedTextureId + return _playerId == MiniController.kUninitializedPlayerId ? Container() : _platform.buildViewWithOptions( - VideoViewOptions(playerId: _textureId), + VideoViewOptions(playerId: _playerId), ); } } diff --git a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart index acc1c8b8c70..c1d16ecce5e 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/messages.g.dart @@ -209,7 +209,7 @@ class AVFoundationVideoPlayerApi { } } - Future dispose(int textureId) async { + Future dispose(int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -219,7 +219,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = - await pigeonVar_channel.send([textureId]) as List?; + await pigeonVar_channel.send([playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -233,7 +233,7 @@ class AVFoundationVideoPlayerApi { } } - Future setLooping(bool isLooping, int textureId) async { + Future setLooping(bool isLooping, int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -243,7 +243,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = await pigeonVar_channel - .send([isLooping, textureId]) as List?; + .send([isLooping, playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -257,7 +257,7 @@ class AVFoundationVideoPlayerApi { } } - Future setVolume(double volume, int textureId) async { + Future setVolume(double volume, int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -267,7 +267,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = await pigeonVar_channel - .send([volume, textureId]) as List?; + .send([volume, playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -281,7 +281,7 @@ class AVFoundationVideoPlayerApi { } } - Future setPlaybackSpeed(double speed, int textureId) async { + Future setPlaybackSpeed(double speed, int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -291,7 +291,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = await pigeonVar_channel - .send([speed, textureId]) as List?; + .send([speed, playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -305,7 +305,7 @@ class AVFoundationVideoPlayerApi { } } - Future play(int textureId) async { + Future play(int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -315,7 +315,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = - await pigeonVar_channel.send([textureId]) as List?; + await pigeonVar_channel.send([playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -329,7 +329,7 @@ class AVFoundationVideoPlayerApi { } } - Future getPosition(int textureId) async { + Future getPosition(int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -339,7 +339,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = - await pigeonVar_channel.send([textureId]) as List?; + await pigeonVar_channel.send([playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -358,7 +358,7 @@ class AVFoundationVideoPlayerApi { } } - Future seekTo(int position, int textureId) async { + Future seekTo(int position, int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -368,7 +368,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = await pigeonVar_channel - .send([position, textureId]) as List?; + .send([position, playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -382,7 +382,7 @@ class AVFoundationVideoPlayerApi { } } - Future pause(int textureId) async { + Future pause(int playerId) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = @@ -392,7 +392,7 @@ class AVFoundationVideoPlayerApi { binaryMessenger: pigeonVar_binaryMessenger, ); final List? pigeonVar_replyList = - await pigeonVar_channel.send([textureId]) as List?; + await pigeonVar_channel.send([playerId]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { diff --git a/packages/video_player/video_player_avfoundation/pigeons/messages.dart b/packages/video_player/video_player_avfoundation/pigeons/messages.dart index 5ed49ea1eab..ffa2f968c32 100644 --- a/packages/video_player/video_player_avfoundation/pigeons/messages.dart +++ b/packages/video_player/video_player_avfoundation/pigeons/messages.dart @@ -55,22 +55,22 @@ abstract class AVFoundationVideoPlayerApi { // Creates a new player and returns its ID. int create(CreationOptions creationOptions); @ObjCSelector('disposePlayer:') - void dispose(int textureId); + void dispose(int playerId); @ObjCSelector('setLooping:forPlayer:') - void setLooping(bool isLooping, int textureId); + void setLooping(bool isLooping, int playerId); @ObjCSelector('setVolume:forPlayer:') - void setVolume(double volume, int textureId); + void setVolume(double volume, int playerId); @ObjCSelector('setPlaybackSpeed:forPlayer:') - void setPlaybackSpeed(double speed, int textureId); + void setPlaybackSpeed(double speed, int playerId); @ObjCSelector('playPlayer:') - void play(int textureId); + void play(int playerId); @ObjCSelector('positionForPlayer:') - int getPosition(int textureId); + int getPosition(int playerId); @async @ObjCSelector('seekTo:forPlayer:') - void seekTo(int position, int textureId); + void seekTo(int position, int playerId); @ObjCSelector('pausePlayer:') - void pause(int textureId); + void pause(int playerId); @ObjCSelector('setMixWithOthers:') void setMixWithOthers(bool mixWithOthers); } diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index 6c3855c0df8..9fc26cea98e 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -12,7 +12,7 @@ import 'test_api.g.dart'; class _ApiLogger implements TestHostVideoPlayerApi { final List log = []; - int? textureId; + int? playerId; CreationOptions? creationOptions; int? position; bool? looping; @@ -28,9 +28,9 @@ class _ApiLogger implements TestHostVideoPlayerApi { } @override - void dispose(int textureId) { + void dispose(int playerId) { log.add('dispose'); - this.textureId = textureId; + this.playerId = playerId; } @override @@ -39,15 +39,15 @@ class _ApiLogger implements TestHostVideoPlayerApi { } @override - void pause(int textureId) { + void pause(int playerId) { log.add('pause'); - this.textureId = textureId; + this.playerId = playerId; } @override - void play(int textureId) { + void play(int playerId) { log.add('play'); - this.textureId = textureId; + this.playerId = playerId; } @override @@ -57,38 +57,38 @@ class _ApiLogger implements TestHostVideoPlayerApi { } @override - int getPosition(int textureId) { + int getPosition(int playerId) { log.add('position'); - this.textureId = textureId; + this.playerId = playerId; return 234; } @override - Future seekTo(int position, int textureId) async { + Future seekTo(int position, int playerId) async { log.add('seekTo'); this.position = position; - this.textureId = textureId; + this.playerId = playerId; } @override - void setLooping(bool loop, int textureId) { + void setLooping(bool loop, int playerId) { log.add('setLooping'); looping = loop; - this.textureId = textureId; + this.playerId = playerId; } @override - void setVolume(double volume, int textureId) { + void setVolume(double volume, int playerId) { log.add('setVolume'); this.volume = volume; - this.textureId = textureId; + this.playerId = playerId; } @override - void setPlaybackSpeed(double speed, int textureId) { + void setPlaybackSpeed(double speed, int playerId) { log.add('setPlaybackSpeed'); playbackSpeed = speed; - this.textureId = textureId; + this.playerId = playerId; } } @@ -123,12 +123,12 @@ void main() { await player.dispose(1); expect(log.log.last, 'dispose'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(player.playerViewStates, isEmpty); }); test('create with asset', () async { - final int? textureId = await player.create(DataSource( + final int? playerId = await player.create(DataSource( sourceType: DataSourceType.asset, asset: 'someAsset', package: 'somePackage', @@ -136,13 +136,13 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('create with network', () async { - final int? textureId = await player.create(DataSource( + final int? playerId = await player.create(DataSource( sourceType: DataSourceType.network, uri: 'someUri', formatHint: VideoFormat.dash, @@ -153,13 +153,13 @@ void main() { expect(log.creationOptions?.packageName, null); expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('create with network (some headers)', () async { - final int? textureId = await player.create(DataSource( + final int? playerId = await player.create(DataSource( sourceType: DataSourceType.network, uri: 'someUri', httpHeaders: {'Authorization': 'Bearer token'}, @@ -171,25 +171,25 @@ void main() { expect(log.creationOptions?.formatHint, null); expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('create with file', () async { - final int? textureId = await player.create(DataSource( + final int? playerId = await player.create(DataSource( sourceType: DataSourceType.file, uri: 'someUri', )); expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with asset', () async { - final int? textureId = await player.createWithOptions( + final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( sourceType: DataSourceType.asset, @@ -202,13 +202,13 @@ void main() { expect(log.log.last, 'create'); expect(log.creationOptions?.asset, 'someAsset'); expect(log.creationOptions?.packageName, 'somePackage'); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with network', () async { - final int? textureId = await player.createWithOptions( + final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( sourceType: DataSourceType.network, @@ -224,13 +224,13 @@ void main() { expect(log.creationOptions?.packageName, null); expect(log.creationOptions?.formatHint, 'dash'); expect(log.creationOptions?.httpHeaders, {}); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with network (some headers)', () async { - final int? textureId = await player.createWithOptions( + final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( sourceType: DataSourceType.network, @@ -247,13 +247,13 @@ void main() { expect(log.creationOptions?.formatHint, null); expect(log.creationOptions?.httpHeaders, {'Authorization': 'Bearer token'}); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); test('createWithOptions with file', () async { - final int? textureId = await player.createWithOptions( + final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( sourceType: DataSourceType.file, @@ -264,7 +264,7 @@ void main() { ); expect(log.log.last, 'create'); expect(log.creationOptions?.uri, 'someUri'); - expect(textureId, 3); + expect(playerId, 3); expect(player.playerViewStates[3], const VideoPlayerTextureViewState(textureId: 3)); }); @@ -288,20 +288,20 @@ void main() { test('setLooping', () async { await player.setLooping(1, true); expect(log.log.last, 'setLooping'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(log.looping, true); }); test('play', () async { await player.play(1); expect(log.log.last, 'play'); - expect(log.textureId, 1); + expect(log.playerId, 1); }); test('pause', () async { await player.pause(1); expect(log.log.last, 'pause'); - expect(log.textureId, 1); + expect(log.playerId, 1); }); test('setMixWithOthers', () async { @@ -317,28 +317,28 @@ void main() { test('setVolume', () async { await player.setVolume(1, 0.7); expect(log.log.last, 'setVolume'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(log.volume, 0.7); }); test('setPlaybackSpeed', () async { await player.setPlaybackSpeed(1, 1.5); expect(log.log.last, 'setPlaybackSpeed'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(log.playbackSpeed, 1.5); }); test('seekTo', () async { await player.seekTo(1, const Duration(milliseconds: 12345)); expect(log.log.last, 'seekTo'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(log.position, 12345); }); test('getPosition', () async { final Duration position = await player.getPosition(1); expect(log.log.last, 'position'); - expect(log.textureId, 1); + expect(log.playerId, 1); expect(position, const Duration(milliseconds: 234)); }); diff --git a/packages/video_player/video_player_avfoundation/test/test_api.g.dart b/packages/video_player/video_player_avfoundation/test/test_api.g.dart index 5fc69e63ccd..38ed42f1f9e 100644 --- a/packages/video_player/video_player_avfoundation/test/test_api.g.dart +++ b/packages/video_player/video_player_avfoundation/test/test_api.g.dart @@ -59,21 +59,21 @@ abstract class TestHostVideoPlayerApi { int create(CreationOptions creationOptions); - void dispose(int textureId); + void dispose(int playerId); - void setLooping(bool isLooping, int textureId); + void setLooping(bool isLooping, int playerId); - void setVolume(double volume, int textureId); + void setVolume(double volume, int playerId); - void setPlaybackSpeed(double speed, int textureId); + void setPlaybackSpeed(double speed, int playerId); - void play(int textureId); + void play(int playerId); - int getPosition(int textureId); + int getPosition(int playerId); - Future seekTo(int position, int textureId); + Future seekTo(int position, int playerId); - void pause(int textureId); + void pause(int playerId); void setMixWithOthers(bool mixWithOthers); @@ -160,11 +160,11 @@ abstract class TestHostVideoPlayerApi { assert(message != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null.'); final List args = (message as List?)!; - final int? arg_textureId = (args[0] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[0] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.dispose was null, expected non-null int.'); try { - api.dispose(arg_textureId!); + api.dispose(arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -195,11 +195,11 @@ abstract class TestHostVideoPlayerApi { final bool? arg_isLooping = (args[0] as bool?); assert(arg_isLooping != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null, expected non-null bool.'); - final int? arg_textureId = (args[1] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[1] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setLooping was null, expected non-null int.'); try { - api.setLooping(arg_isLooping!, arg_textureId!); + api.setLooping(arg_isLooping!, arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -230,11 +230,11 @@ abstract class TestHostVideoPlayerApi { final double? arg_volume = (args[0] as double?); assert(arg_volume != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null, expected non-null double.'); - final int? arg_textureId = (args[1] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[1] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setVolume was null, expected non-null int.'); try { - api.setVolume(arg_volume!, arg_textureId!); + api.setVolume(arg_volume!, arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -265,11 +265,11 @@ abstract class TestHostVideoPlayerApi { final double? arg_speed = (args[0] as double?); assert(arg_speed != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null, expected non-null double.'); - final int? arg_textureId = (args[1] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[1] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setPlaybackSpeed was null, expected non-null int.'); try { - api.setPlaybackSpeed(arg_speed!, arg_textureId!); + api.setPlaybackSpeed(arg_speed!, arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -297,11 +297,11 @@ abstract class TestHostVideoPlayerApi { assert(message != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null.'); final List args = (message as List?)!; - final int? arg_textureId = (args[0] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[0] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.play was null, expected non-null int.'); try { - api.play(arg_textureId!); + api.play(arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -329,11 +329,11 @@ abstract class TestHostVideoPlayerApi { assert(message != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null.'); final List args = (message as List?)!; - final int? arg_textureId = (args[0] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[0] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getPosition was null, expected non-null int.'); try { - final int output = api.getPosition(arg_textureId!); + final int output = api.getPosition(arg_playerId!); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -364,11 +364,11 @@ abstract class TestHostVideoPlayerApi { final int? arg_position = (args[0] as int?); assert(arg_position != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null, expected non-null int.'); - final int? arg_textureId = (args[1] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[1] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.seekTo was null, expected non-null int.'); try { - await api.seekTo(arg_position!, arg_textureId!); + await api.seekTo(arg_position!, arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -396,11 +396,11 @@ abstract class TestHostVideoPlayerApi { assert(message != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null.'); final List args = (message as List?)!; - final int? arg_textureId = (args[0] as int?); - assert(arg_textureId != null, + final int? arg_playerId = (args[0] as int?); + assert(arg_playerId != null, 'Argument for dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.pause was null, expected non-null int.'); try { - api.pause(arg_textureId!); + api.pause(arg_playerId!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); From ebe123a2217f52d11340ce1ee2eca4eb98f62109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 11:40:53 +0100 Subject: [PATCH 140/167] Move dispose guard to texture-based video player, simplify unregistering texture logic --- .../FVPTextureBasedVideoPlayer.m | 8 ++++++++ .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 8 -------- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 6 +----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index a4a3fd34207..506fa61d461 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -144,6 +144,14 @@ - (void)seekTo:(int64_t)location completionHandler:(void (^)(BOOL))completionHan } - (void)disposeSansEventChannel { + // This check prevents the crash caused by removing the KVO observers twice. + // When performing a Hot Restart, the leftover players are disposed once directly + // by [FVPVideoPlayerPlugin initialize:] method and then disposed again by + // [FVPVideoPlayer onTextureUnregistered:] call leading to possible over-release. + if (self.disposed) { + return; + } + [super disposeSansEventChannel]; [self.playerLayer removeFromSuperlayer]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 9cfe12ecffc..6dba1c35b66 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -469,14 +469,6 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments /// is useful for the case where the Engine is in the process of deconstruction /// so the channel is going to die or is already dead. - (void)disposeSansEventChannel { - // This check prevents the crash caused by removing the KVO observers twice. - // When performing a Hot Restart, the leftover players are disposed once directly - // by [FVPVideoPlayerPlugin initialize:] method and then disposed again by - // [FVPVideoPlayer onTextureUnregistered:] call leading to possible over-release. - if (_disposed) { - return; - } - _disposed = YES; [self removeKeyValueObservers]; 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 9ad702ccb44..eb038b171d6 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 @@ -163,11 +163,7 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { upgradeAudioSessionCategory(AVAudioSessionCategoryPlayback, 0, 0); #endif - [self.playersById - enumerateKeysAndObjectsUsingBlock:^(NSNumber *textureId, FVPVideoPlayer *player, BOOL *stop) { - [self.registry unregisterTexture:textureId.unsignedIntegerValue]; - [player dispose]; - }]; + [self.playersById.allValues makeObjectsPerformSelector:@selector(dispose)]; [self.playersById removeAllObjects]; } From d486095d1145f751a1ef61577c0b48e3a686d703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 11:42:48 +0100 Subject: [PATCH 141/167] Rename textureId to playerId in iOS native code --- .../darwin/RunnerTests/VideoPlayerTests.m | 94 +++++++++---------- .../video_player_avfoundation/messages.g.h | 16 ++-- .../video_player_avfoundation/messages.g.m | 32 +++---- 3 files changed, 71 insertions(+), 71 deletions(-) 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 b993f76c5dd..3b7aae8f598 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -187,9 +187,9 @@ - (void)testCreateWithOptionsReturnsErrorForInvalidAssetPath { viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; - XCTAssertNil(textureId); + XCTAssertNil(playerId); XCTAssertNotNil(createError); XCTAssertEqualObjects(createError.code, @"video_player"); } @@ -216,11 +216,11 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(textureId); + XCTAssertNotNil(playerId); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present."); @@ -292,15 +292,15 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; // Ensure that the video playback is paused before seeking. FlutterError *pauseError; - [videoPlayerPlugin pausePlayer:textureId.integerValue error:&pauseError]; + [videoPlayerPlugin pausePlayer:playerId.integerValue error:&pauseError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo completes"]; [videoPlayerPlugin seekTo:1234 - forPlayer:textureId.integerValue + forPlayer:playerId.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -309,7 +309,7 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { // Seeking to a new position should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; // Wait for the player's position to update, it shouldn't take long. XCTestExpectation *positionExpectation = [self expectationForPredicate:[NSPredicate predicateWithFormat:@"position == 1234"] @@ -364,7 +364,7 @@ - (void)testInitStartsDisplayLinkTemporarily { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; // Init should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); @@ -380,7 +380,7 @@ - (void)testInitStartsDisplayLinkTemporarily { .andReturn(fakeBufferRef); // Simulate a callback from the engine to request a new frame. FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; [player copyPixelBuffer]; // Since a frame was found, and the video is paused, the display link should be paused again. OCMVerify([mockDisplayLink setRunning:NO]); @@ -416,15 +416,15 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; // Ensure that the video is playing before seeking. FlutterError *playError; - [videoPlayerPlugin playPlayer:textureId.integerValue error:&playError]; + [videoPlayerPlugin playPlayer:playerId.integerValue error:&playError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo completes"]; [videoPlayerPlugin seekTo:1234 - forPlayer:textureId.integerValue + forPlayer:playerId.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -432,7 +432,7 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { OCMVerify([mockDisplayLink setRunning:YES]); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -480,12 +480,12 @@ - (void)testPauseWhileWaitingForFrameDoesNotStopDisplayLink { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; // Run a play/pause cycle to force the pause codepath to run completely. FlutterError *playPauseError; - [videoPlayerPlugin playPlayer:textureId.integerValue error:&playPauseError]; - [videoPlayerPlugin pausePlayer:textureId.integerValue error:&playPauseError]; + [videoPlayerPlugin playPlayer:playerId.integerValue error:&playPauseError]; + [videoPlayerPlugin pausePlayer:playerId.integerValue error:&playPauseError]; // Since a buffer hasn't been available yet, the pause should not have stopped the display link. OCMVerify(never(), [mockDisplayLink setRunning:NO]); @@ -508,16 +508,16 @@ - (void)testDeregistersFromPlayer { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + XCTAssertNotNil(playerId); + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [self keyValueObservingExpectationForObject:avPlayer keyPath:@"currentItem" expectedValue:nil]; - [videoPlayerPlugin disposePlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin disposePlayer:playerId.integerValue error:&error]; XCTAssertEqual(videoPlayerPlugin.playersById.count, 0); XCTAssertNil(error); @@ -541,10 +541,10 @@ - (void)testBufferingStateFromPlayer { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(textureId); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + XCTAssertNotNil(playerId); + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [avPlayer play]; @@ -668,12 +668,12 @@ - (void)testSeekToleranceWhenNotSeekingToEnd { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; + NSNumber *playerId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo has zero tolerance when seeking not to end"]; [pluginWithMockAVPlayer seekTo:1234 - forPlayer:textureId.integerValue + forPlayer:playerId.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -707,13 +707,13 @@ - (void)testSeekToleranceWhenSeekingToEnd { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *textureId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; + NSNumber *playerId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo has non-zero tolerance when seeking to end"]; // The duration of this video is "0" due to the non standard initiliatazion process. [pluginWithMockAVPlayer seekTo:0 - forPlayer:textureId.integerValue + forPlayer:playerId.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -735,9 +735,9 @@ - (void)testSeekToleranceWhenSeekingToEnd { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; @@ -759,15 +759,15 @@ - (void)testSeekToleranceWhenSeekingToEnd { XCTAssertEqual(avPlayer.timeControlStatus, AVPlayerTimeControlStatusPaused); // Change playback speed. - [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerId.integerValue error:&error]; XCTAssertNil(error); - [videoPlayerPlugin playPlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin playPlayer:playerId.integerValue error:&error]; XCTAssertNil(error); XCTAssertEqual(avPlayer.rate, 2); XCTAssertEqual(avPlayer.timeControlStatus, AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate); // Volume - [videoPlayerPlugin setVolume:0.1 forPlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin setVolume:0.1 forPlayer:playerId.integerValue error:&error]; XCTAssertNil(error); XCTAssertEqual(avPlayer.volume, 0.1f); @@ -803,16 +803,16 @@ - (void)testDoesNotCrashOnRateObservationAfterDisposal { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(textureId); + XCTAssertNotNil(playerId); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); weakPlayer = player; avPlayer = player.player; - [videoPlayerPlugin disposePlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin disposePlayer:playerId.integerValue error:&error]; XCTAssertNil(error); } @@ -858,12 +858,12 @@ - (void)testHotReloadDoesNotCrash { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(textureId); + XCTAssertNotNil(playerId); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[textureId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); weakPlayer = player; @@ -938,8 +938,8 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTAssertNotNil(player); [self keyValueObservingExpectationForObject:(id)player.player.currentItem @@ -976,8 +976,8 @@ - (void)testUpdatePlayingStateShouldNotResetRate { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *textureId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[textureId]; + NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; [player onListenWithArguments:nil @@ -988,8 +988,8 @@ - (void)testUpdatePlayingStateShouldNotResetRate { }]; [self waitForExpectationsWithTimeout:10 handler:nil]; - [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:textureId.integerValue error:&error]; - [videoPlayerPlugin playPlayer:textureId.integerValue error:&error]; + [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin playPlayer:playerId.integerValue error:&error]; XCTAssertEqual(player.player.rate, 2); } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h index cec06e43c72..6a115c6b9ac 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/messages.g.h @@ -61,24 +61,24 @@ NSObject *FVPGetMessagesCodec(void); /// @return `nil` only when `error != nil`. - (nullable NSNumber *)createWithOptions:(FVPCreationOptions *)creationOptions error:(FlutterError *_Nullable *_Nonnull)error; -- (void)disposePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)disposePlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setLooping:(BOOL)isLooping - forPlayer:(NSInteger)textureId + forPlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setVolume:(double)volume - forPlayer:(NSInteger)textureId + forPlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setPlaybackSpeed:(double)speed - forPlayer:(NSInteger)textureId + forPlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; -- (void)playPlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)playPlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; /// @return `nil` only when `error != nil`. -- (nullable NSNumber *)positionForPlayer:(NSInteger)textureId +- (nullable NSNumber *)positionForPlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; - (void)seekTo:(NSInteger)position - forPlayer:(NSInteger)textureId + forPlayer:(NSInteger)playerId completion:(void (^)(FlutterError *_Nullable))completion; -- (void)pausePlayer:(NSInteger)textureId error:(FlutterError *_Nullable *_Nonnull)error; +- (void)pausePlayer:(NSInteger)playerId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setMixWithOthers:(BOOL)mixWithOthers error:(FlutterError *_Nullable *_Nonnull)error; @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m index 74b6a4ec118..83c41211f74 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/messages.g.m @@ -251,9 +251,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - [api disposePlayer:arg_textureId error:&error]; + [api disposePlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -276,9 +276,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; BOOL arg_isLooping = [GetNullableObjectAtIndex(args, 0) boolValue]; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 1) integerValue]; FlutterError *error; - [api setLooping:arg_isLooping forPlayer:arg_textureId error:&error]; + [api setLooping:arg_isLooping forPlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -301,9 +301,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_volume = [GetNullableObjectAtIndex(args, 0) doubleValue]; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 1) integerValue]; FlutterError *error; - [api setVolume:arg_volume forPlayer:arg_textureId error:&error]; + [api setVolume:arg_volume forPlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -326,9 +326,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; double arg_speed = [GetNullableObjectAtIndex(args, 0) doubleValue]; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 1) integerValue]; FlutterError *error; - [api setPlaybackSpeed:arg_speed forPlayer:arg_textureId error:&error]; + [api setPlaybackSpeed:arg_speed forPlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -350,9 +350,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - [api playPlayer:arg_textureId error:&error]; + [api playPlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -374,9 +374,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - NSNumber *output = [api positionForPlayer:arg_textureId error:&error]; + NSNumber *output = [api positionForPlayer:arg_playerId error:&error]; callback(wrapResult(output, error)); }]; } else { @@ -399,9 +399,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSInteger arg_position = [GetNullableObjectAtIndex(args, 0) integerValue]; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 1) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 1) integerValue]; [api seekTo:arg_position - forPlayer:arg_textureId + forPlayer:arg_playerId completion:^(FlutterError *_Nullable error) { callback(wrapResult(nil, error)); }]; @@ -425,9 +425,9 @@ void SetUpFVPAVFoundationVideoPlayerApiWithSuffix(id bin api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSInteger arg_textureId = [GetNullableObjectAtIndex(args, 0) integerValue]; + NSInteger arg_playerId = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - [api pausePlayer:arg_textureId error:&error]; + [api pausePlayer:arg_playerId error:&error]; callback(wrapResult(nil, error)); }]; } else { From cdd145830e2ddefb231764e7c19d0d476b2fb108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 11:47:08 +0100 Subject: [PATCH 142/167] Bump platform interface dependency to 6.3.0 in example app --- .../video_player_avfoundation/example/pubspec.yaml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/pubspec.yaml b/packages/video_player/video_player_avfoundation/example/pubspec.yaml index 4b80f552419..5be28a5fa34 100644 --- a/packages/video_player/video_player_avfoundation/example/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/example/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - video_player_platform_interface: ">=6.1.0 <7.0.0" + video_player_platform_interface: ">=6.3.0 <7.0.0" dev_dependencies: flutter_test: @@ -31,13 +31,3 @@ flutter: assets: - assets/flutter-mark-square-64.png - assets/Butterfly-209.mp4 - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins -dependency_overrides: - { - video_player_platform_interface: - { - path: ../../../../packages/video_player/video_player_platform_interface, - }, - } From f920a388dfc14764d0830be8afb150cf442f94a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 28 Jan 2025 14:26:17 +0100 Subject: [PATCH 143/167] Remove outdated information from doc comment --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index e2d4aa22441..752656ac8a2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -17,8 +17,7 @@ NS_ASSUME_NONNULL_BEGIN /// FVPVideoPlayer is responsible for managing video playback using AVPlayer. -/// It provides methods to control playback, adjust volume, handle seeking, and -/// notify the Flutter engine about new video frames. +/// It provides methods to control playback, adjust volume, and handle seeking. @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; From 84a0538d8df73bb3abec2acfb6779971e07aeb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 29 Jan 2025 09:41:20 +0100 Subject: [PATCH 144/167] Rename FromOptions to WithOptions --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 eb038b171d6..9aecb4d23e6 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 @@ -174,9 +174,9 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options @try { FVPVideoPlayer *player; if (textureBased) { - player = [self createTextureBasedPlayerFromOptions:options]; + player = [self createTextureBasedPlayerWithOptions:options]; } else { - player = [self createRegularPlayerFromOptions:options]; + player = [self createRegularPlayerWithOptions:options]; } if (player == nil) { @@ -191,7 +191,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } -- (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerFromOptions: +- (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerWithOptions: (nonnull FVPCreationOptions *)options { FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; FVPDisplayLink *displayLink = @@ -225,7 +225,7 @@ - (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerFromOptions: return nil; } -- (nullable FVPVideoPlayer *)createRegularPlayerFromOptions:(nonnull FVPCreationOptions *)options { +- (nullable FVPVideoPlayer *)createRegularPlayerWithOptions:(nonnull FVPCreationOptions *)options { if (options.asset) { NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; return [[FVPVideoPlayer alloc] initWithAsset:assetPath From d1841b3e4045779da95436622970eeb48f9f7fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 29 Jan 2025 09:49:40 +0100 Subject: [PATCH 145/167] Use weak self to avoid retain cycles --- .../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 9aecb4d23e6..7ea18daac64 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 @@ -200,8 +200,9 @@ - (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerWithOptions: [frameUpdater displayLinkFired]; }]; + __weak typeof(self) weakSelf = self; void (^onDisposed)(int64_t) = ^(int64_t textureId) { - [self.registry unregisterTexture:textureId]; + [weakSelf.registry unregisterTexture:textureId]; }; if (options.asset) { From 29cddaf26d1c67e5a3afd3b1c96f52bf9c6a9754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 29 Jan 2025 11:00:37 +0100 Subject: [PATCH 146/167] Rename create-player methods --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 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 7ea18daac64..855a4068dae 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 @@ -174,9 +174,9 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options @try { FVPVideoPlayer *player; if (textureBased) { - player = [self createTextureBasedPlayerWithOptions:options]; + player = [self createTexturePlayerWithOptions:options]; } else { - player = [self createRegularPlayerWithOptions:options]; + player = [self createPlatformViewPlayerWithOptions:options]; } if (player == nil) { @@ -191,7 +191,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } -- (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerWithOptions: +- (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: (nonnull FVPCreationOptions *)options { FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; FVPDisplayLink *displayLink = @@ -226,7 +226,8 @@ - (nullable FVPTextureBasedVideoPlayer *)createTextureBasedPlayerWithOptions: return nil; } -- (nullable FVPVideoPlayer *)createRegularPlayerWithOptions:(nonnull FVPCreationOptions *)options { +- (nullable FVPVideoPlayer *)createPlatformViewPlayerWithOptions: + (nonnull FVPCreationOptions *)options { if (options.asset) { NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; return [[FVPVideoPlayer alloc] initWithAsset:assetPath From db469b342180af88a41ac2cc12d66f2beaf065a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 29 Jan 2025 11:04:33 +0100 Subject: [PATCH 147/167] Comment on using FVPVideoPlayer --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 1 + 1 file changed, 1 insertion(+) 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 855a4068dae..ae8f33bfc2f 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 @@ -228,6 +228,7 @@ - (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: - (nullable FVPVideoPlayer *)createPlatformViewPlayerWithOptions: (nonnull FVPCreationOptions *)options { + // FVPVideoPlayer contains all required logic for platform views. if (options.asset) { NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; return [[FVPVideoPlayer alloc] initWithAsset:assetPath From 417e7716df27150aa5c3cc17af61215a341517ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 29 Jan 2025 16:44:07 +0100 Subject: [PATCH 148/167] Fall back to texture view if platform view is requested on MacOS --- .../example/lib/main.dart | 2 +- .../lib/src/avfoundation_video_player.dart | 9 ++++++-- .../test/avfoundation_video_player_test.dart | 23 ++++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index d195f91a9b5..0067b639c96 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -59,7 +59,7 @@ class _App extends StatelessWidget { _ButterFlyAssetVideo(viewType), ), ] - // We don't support platform views on MacOS yet. + // Platform views are only supported on iOS as of now. : const [ _BumbleBeeRemoteVideo(VideoViewType.textureView), _BumbleBeeEncryptedLiveStream(VideoViewType.textureView), diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index 91b01c20e4d..ec790187abf 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -52,6 +53,10 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future createWithOptions(VideoCreationOptions options) async { final DataSource dataSource = options.dataSource; + // Platform views are not supported on macOS yet. Use texture view instead. + final VideoViewType viewType = defaultTargetPlatform == TargetPlatform.macOS + ? VideoViewType.textureView + : options.viewType; String? asset; String? packageName; @@ -77,11 +82,11 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { uri: uri, httpHeaders: httpHeaders, formatHint: formatHint, - viewType: _platformVideoViewTypeFromVideoViewType(options.viewType), + viewType: _platformVideoViewTypeFromVideoViewType(viewType), ); final int playerId = await _api.create(pigeonCreationOptions); - playerViewStates[playerId] = switch (options.viewType) { + playerViewStates[playerId] = switch (viewType) { // playerId is also the textureId when using texture view. VideoViewType.textureView => VideoPlayerTextureViewState(textureId: playerId), diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index 9fc26cea98e..3d02cef3cbe 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -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 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:video_player_avfoundation/src/messages.g.dart'; @@ -269,7 +270,8 @@ void main() { const VideoPlayerTextureViewState(textureId: 3)); }); - test('createWithOptions with platform view', () async { + test('createWithOptions with platform view on iOS', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( @@ -285,6 +287,25 @@ void main() { expect(player.playerViewStates[3], const VideoPlayerPlatformViewState()); }); + test('createWithOptions with platform view uses texture view on MacOS', + () async { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; + final int? playerId = await player.createWithOptions( + VideoCreationOptions( + dataSource: DataSource( + sourceType: DataSourceType.file, + uri: 'someUri', + ), + viewType: VideoViewType.platformView, + ), + ); + expect(log.log.last, 'create'); + expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); + expect(playerId, 3); + expect(player.playerViewStates[3], + const VideoPlayerTextureViewState(textureId: 3)); + }); + test('setLooping', () async { await player.setLooping(1, true); expect(log.log.last, 'setLooping'); From c1497d76c36d5f6789ce759087c1b2f80e015e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Thu, 30 Jan 2025 10:58:29 +0100 Subject: [PATCH 149/167] Describe missing support for MacOS platform views in readme --- packages/video_player/video_player_avfoundation/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/README.md b/packages/video_player/video_player_avfoundation/README.md index 1325daf0acf..4faad213513 100644 --- a/packages/video_player/video_player_avfoundation/README.md +++ b/packages/video_player/video_player_avfoundation/README.md @@ -13,3 +13,7 @@ should add it to your `pubspec.yaml` as usual. [1]: https://pub.dev/packages/video_player [2]: https://flutter.dev/to/endorsed-federated-plugin + +## Platform limitations + +On macOS, the plugin does not support platform views. Instead, a texture view is always used to display the video player, even if `VideoViewType.platformView` is specified as a parameter. \ No newline at end of file From b7dc9ff1847fbe08c0d67919e97f3fa1557fc7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 4 Feb 2025 09:32:32 +0100 Subject: [PATCH 150/167] Remove flutterViewLayer from FVPVideoPlayer interface --- .../include/video_player_avfoundation/FVPVideoPlayer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 752656ac8a2..2009cb808e6 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -72,8 +72,6 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly) AVPlayerItemVideoOutput *videoOutput; /// The plugin registrar, to obtain view information from. @property(nonatomic, readonly) NSObject *registrar; -/// The CALayer associated with the Flutter view this plugin is associated with, if any. -@property(nonatomic, readonly, nullable) CALayer *flutterViewLayer; /// The Flutter event sink used to send events to the Flutter engine. @property(nonatomic) FlutterEventSink eventSink; /// The preferred transform for the video. It can be used to handle the rotation of the video. From ecfd81fe25e9baacdaa21abec51d215f92e91f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 4 Feb 2025 10:58:23 +0100 Subject: [PATCH 151/167] Add more details to comments in FVPTextureBasedVideoPlayer and FVPVideoPlayer --- .../FVPTextureBasedVideoPlayer.h | 1 + .../FVPVideoPlayer.h | 7 +++++-- .../ios/Runner.xcodeproj/project.pbxproj | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index 90cfae4633e..5ac4f729cb6 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN /// A subclass of FVPVideoPlayer that adds functionality related to texture-based view as a way of /// displaying the video in the app. It manages the CALayer associated with the Flutter view, /// updates frames, and handles display link callbacks. +/// If you need to display a video using platform view, use FVPVideoPlayer instead. @interface FVPTextureBasedVideoPlayer : FVPVideoPlayer /// Initializes a new instance of FVPTextureBasedVideoPlayer with the given URL, frame updater, /// display link, HTTP headers, AV factory, and registrar. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 2009cb808e6..0128503df52 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -16,8 +16,11 @@ NS_ASSUME_NONNULL_BEGIN -/// FVPVideoPlayer is responsible for managing video playback using AVPlayer. -/// It provides methods to control playback, adjust volume, and handle seeking. +/// FVPVideoPlayer manages video playback using AVPlayer. +/// It provides methods for controlling playback, adjusting volume, and handling seeking. +/// This class contains all functionalities needed to manage video playback in platform views and is +/// typically used alongside FVPNativeVideoViewFactory. If you need to display a video using a +/// texture, use FVPTextureBasedVideoPlayer instead. @interface FVPVideoPlayer : NSObject /// The Flutter event channel used to communicate with the Flutter engine. @property(nonatomic) FlutterEventChannel *eventChannel; diff --git a/packages/video_player/video_player_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/video_player/video_player_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 94ce699b626..e8166db9ca2 100644 --- a/packages/video_player/video_player_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/video_player/video_player_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -220,6 +220,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 39F8523A410339490F826122 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -350,6 +351,26 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 39F8523A410339490F826122 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation/path_provider_foundation_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/video_player_avfoundation/video_player_avfoundation_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/path_provider_foundation_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/video_player_avfoundation_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; From a740fa2026195799ba8c7d1ca72c2c31a62630a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 15:42:07 +0100 Subject: [PATCH 152/167] Simplify version constraints in pubspec.yaml --- .../video_player/video_player_avfoundation/example/pubspec.yaml | 2 +- packages/video_player/video_player_avfoundation/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/example/pubspec.yaml b/packages/video_player/video_player_avfoundation/example/pubspec.yaml index 5be28a5fa34..9441576e59d 100644 --- a/packages/video_player/video_player_avfoundation/example/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/example/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - video_player_platform_interface: ">=6.3.0 <7.0.0" + video_player_platform_interface: ^6.3.0 dev_dependencies: flutter_test: diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 9b4bbb6627e..3db089c7ccf 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -24,7 +24,7 @@ flutter: dependencies: flutter: sdk: flutter - video_player_platform_interface: ">=6.3.0 <7.0.0" + video_player_platform_interface: ^6.3.0 dev_dependencies: flutter_test: From 7071a66fc35951c2d5fbe80a6b9a0fbbe1dc37ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 15:47:22 +0100 Subject: [PATCH 153/167] Clarify that the lack of macOS support is not a fundamental limitation --- packages/video_player/video_player_avfoundation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/README.md b/packages/video_player/video_player_avfoundation/README.md index 4faad213513..f46470ee2f5 100644 --- a/packages/video_player/video_player_avfoundation/README.md +++ b/packages/video_player/video_player_avfoundation/README.md @@ -16,4 +16,4 @@ should add it to your `pubspec.yaml` as usual. ## Platform limitations -On macOS, the plugin does not support platform views. Instead, a texture view is always used to display the video player, even if `VideoViewType.platformView` is specified as a parameter. \ No newline at end of file +On macOS, the plugin does not currently support platform views. Instead, a texture view is always used to display the video player, even if `VideoViewType.platformView` is specified as a parameter. \ No newline at end of file From 0a80da6700b5ca2ce9a4e6fe106604a5929e2ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 15:55:45 +0100 Subject: [PATCH 154/167] Put conditional imports at the end --- .../video_player_avfoundation/FVPFrameUpdater.h | 4 ++-- .../video_player_avfoundation/FVPNativeVideoView.h | 4 +--- .../FVPNativeVideoViewFactory.h | 4 ++-- .../FVPTextureBasedVideoPlayer_Test.h | 4 ++-- .../video_player_avfoundation/FVPVideoPlayer.h | 12 ++++++------ .../video_player_avfoundation/FVPVideoPlayer_Test.h | 4 ++-- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index 1e07ca9f019..11f88dcbff2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import + #if TARGET_OS_OSX #import #else #import #endif -#import - NS_ASSUME_NONNULL_BEGIN /// FVPFrameUpdater is responsible for notifying the Flutter texture registry diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index 8c53ac1c017..f05ebccf991 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -4,7 +4,7 @@ // Platform views are only supported on iOS as of now. Ifdefs are used to avoid compilation errors. -#import +#import #if TARGET_OS_OSX #import @@ -12,8 +12,6 @@ #import #endif -#import - /// A class used to create a native video view that can be embedded in a Flutter app. /// This class wraps an AVPlayer instance and displays its video content. #if TARGET_OS_IOS diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index 655752ded0f..4fae5713a0a 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -6,14 +6,14 @@ #import +#import "FVPVideoPlayer.h" + #if TARGET_OS_OSX #import #else #import #endif -#import "FVPVideoPlayer.h" - /// A factory class responsible for creating native video views that can be embedded in a /// Flutter app. @interface FVPNativeVideoViewFactory : NSObject diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h index 2e5366360bc..b751311f5c8 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "FVPTextureBasedVideoPlayer.h" + #if TARGET_OS_OSX #import #else #import #endif -#import "FVPTextureBasedVideoPlayer.h" - NS_ASSUME_NONNULL_BEGIN @interface FVPTextureBasedVideoPlayer () diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index 0128503df52..fe588856195 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if TARGET_OS_OSX -#import -#else -#import -#endif - #import #import "FVPAVFactory.h" #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" +#if TARGET_OS_OSX +#import +#else +#import +#endif + NS_ASSUME_NONNULL_BEGIN /// FVPVideoPlayer manages video playback using AVPlayer. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h index 2f2ad85e989..967855d85bd 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Test.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "FVPVideoPlayer.h" + #if TARGET_OS_OSX #import #else #import #endif -#import "FVPVideoPlayer.h" - NS_ASSUME_NONNULL_BEGIN @interface FVPVideoPlayer () From ec18e13a0fccdbf9226282045d6b8db485e96d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 16:41:13 +0100 Subject: [PATCH 155/167] Extract common logic to a shared method --- .../FVPTextureBasedVideoPlayer.m | 10 +------- .../FVPVideoPlayer.m | 23 +++++++++++-------- .../FVPVideoPlayer.h | 4 ++++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 506fa61d461..59d6b5c3193 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -25,15 +25,7 @@ - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar onDisposed:(void (^)(int64_t))onDisposed { - NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; -#if TARGET_OS_OSX - // See https://github.com/flutter/flutter/issues/135302 - // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. - if (!path) { - path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; - } -#endif - return [self initWithURL:[NSURL fileURLWithPath:path] + return [self initWithURL:[NSURL fileURLWithPath:[self getAbsoluteAssetPath:asset]] frameUpdater:frameUpdater displayLink:displayLink httpHeaders:@{} diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 6dba1c35b66..23655f6bbe2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -20,15 +20,7 @@ @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar { - NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; -#if TARGET_OS_OSX - // See https://github.com/flutter/flutter/issues/135302 - // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. - if (!path) { - path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; - } -#endif - return [self initWithURL:[NSURL fileURLWithPath:path] + return [self initWithURL:[NSURL fileURLWithPath:[self getAbsoluteAssetPath:asset]] httpHeaders:@{} avFactory:avFactory registrar:registrar]; @@ -107,6 +99,19 @@ - (void)dealloc { } } +- (NSString *)getAbsoluteAssetPath:(NSString *)asset { + NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; +#if TARGET_OS_OSX + // See https://github.com/flutter/flutter/issues/135302 + // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. + if (!path) { + path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; + } +#endif + + return path; +} + - (void)addObserversForItem:(AVPlayerItem *)item player:(AVPlayer *)player { [item addObserver:self forKeyPath:@"loadedTimeRanges" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index fe588856195..ff20f7231a1 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -94,6 +94,10 @@ NS_ASSUME_NONNULL_BEGIN /// Updates the playing state of the video player. - (void)updatePlayingState; + +/// Returns the absolute file path for a given asset name. +/// This method attempts to locate the specified asset within the app bundle. +- (NSString *)getAbsoluteAssetPath:(NSString *)asset; @end NS_ASSUME_NONNULL_END From 3b55eec9e298ef1cc8b1b0a0e3cdfd5b80ce8eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 17:29:03 +0100 Subject: [PATCH 156/167] Move FVPVideoPlayer class extension to _Internal.h file --- .../FVPTextureBasedVideoPlayer.m | 2 +- .../FVPVideoPlayer.m | 2 +- .../FVPTextureBasedVideoPlayer.h | 2 +- .../FVPVideoPlayer.h | 32 ------------- .../FVPVideoPlayer_Internal.h | 47 +++++++++++++++++++ 5 files changed, 50 insertions(+), 35 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 59d6b5c3193..3aeaa6fba20 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FVPTextureBasedVideoPlayer_Test.h" +#import "./include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h" @interface FVPTextureBasedVideoPlayer () // The CALayer associated with the Flutter view this plugin is associated with, if any. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 23655f6bbe2..0613f610424 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "./include/video_player_avfoundation/FVPVideoPlayer.h" +#import "./include/video_player_avfoundation/FVPVideoPlayer_Internal.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" #import diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index 5ac4f729cb6..c1c535e4245 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -4,7 +4,7 @@ #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" -#import "FVPVideoPlayer.h" +#import "FVPVideoPlayer_Internal.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h index ff20f7231a1..d668c820065 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h @@ -5,8 +5,6 @@ #import #import "FVPAVFactory.h" -#import "FVPDisplayLink.h" -#import "FVPFrameUpdater.h" #if TARGET_OS_OSX #import @@ -70,34 +68,4 @@ NS_ASSUME_NONNULL_BEGIN - (void)seekTo:(int64_t)location completionHandler:(void (^_Nullable)(BOOL))completionHandler; @end -@interface FVPVideoPlayer () -/// The AVPlayerItemVideoOutput associated with this video player. -@property(nonatomic, readonly) AVPlayerItemVideoOutput *videoOutput; -/// The plugin registrar, to obtain view information from. -@property(nonatomic, readonly) NSObject *registrar; -/// The Flutter event sink used to send events to the Flutter engine. -@property(nonatomic) FlutterEventSink eventSink; -/// The preferred transform for the video. It can be used to handle the rotation of the video. -@property(nonatomic) CGAffineTransform preferredTransform; -/// The target playback speed requested by the plugin client. -@property(nonatomic, readonly) NSNumber *targetPlaybackSpeed; -/// Indicates whether the video player is currently playing. -@property(nonatomic, readonly) BOOL isPlaying; -/// Indicates whether the video player has been initialized. -@property(nonatomic, readonly) BOOL isInitialized; - -/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display -/// link, AV factory, and registrar. -- (instancetype)initWithPlayerItem:(AVPlayerItem *)item - avFactory:(id)avFactory - registrar:(NSObject *)registrar; - -/// Updates the playing state of the video player. -- (void)updatePlayingState; - -/// Returns the absolute file path for a given asset name. -/// This method attempts to locate the specified asset within the app bundle. -- (NSString *)getAbsoluteAssetPath:(NSString *)asset; -@end - NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h new file mode 100644 index 00000000000..67443c6ef29 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h @@ -0,0 +1,47 @@ +// 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 +#import "FVPAVFactory.h" +#import "FVPVideoPlayer.h" + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface FVPVideoPlayer () +/// The AVPlayerItemVideoOutput associated with this video player. +@property(nonatomic, readonly) AVPlayerItemVideoOutput *videoOutput; +/// The plugin registrar, to obtain view information from. +@property(nonatomic, readonly) NSObject *registrar; +/// The Flutter event sink used to send events to the Flutter engine. +@property(nonatomic) FlutterEventSink eventSink; +/// The preferred transform for the video. It can be used to handle the rotation of the video. +@property(nonatomic) CGAffineTransform preferredTransform; +/// The target playback speed requested by the plugin client. +@property(nonatomic, readonly) NSNumber *targetPlaybackSpeed; +/// Indicates whether the video player is currently playing. +@property(nonatomic, readonly) BOOL isPlaying; +/// Indicates whether the video player has been initialized. +@property(nonatomic, readonly) BOOL isInitialized; + +/// Initializes a new instance of FVPVideoPlayer with the given AVPlayerItem, frame updater, display +/// link, AV factory, and registrar. +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item + avFactory:(id)avFactory + registrar:(NSObject *)registrar; + +/// Updates the playing state of the video player. +- (void)updatePlayingState; + +/// Returns the absolute file path for a given asset name. +/// This method attempts to locate the specified asset within the app bundle. +- (NSString *)getAbsoluteAssetPath:(NSString *)asset; +@end + +NS_ASSUME_NONNULL_END From c694d865e8ab3585cc74530683ddf69174beca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Wed, 5 Feb 2025 18:34:51 +0100 Subject: [PATCH 157/167] Rename Id to Identifier where possible --- .../darwin/RunnerTests/VideoPlayerTests.m | 96 +++++++++---------- .../FVPFrameUpdater.m | 2 +- .../FVPTextureBasedVideoPlayer.m | 6 +- .../FVPVideoPlayerPlugin.m | 91 ++++++++++-------- .../FVPFrameUpdater.h | 4 +- .../FVPNativeVideoViewFactory.h | 4 +- .../FVPTextureBasedVideoPlayer.h | 6 +- .../FVPVideoPlayerPlugin_Test.h | 2 +- .../FVPNativeVideoViewFactory.m | 8 +- 9 files changed, 113 insertions(+), 106 deletions(-) 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 3b7aae8f598..4e6e13db93f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -187,9 +187,9 @@ - (void)testCreateWithOptionsReturnsErrorForInvalidAssetPath { viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&createError]; - XCTAssertNil(playerId); + XCTAssertNil(playerIdentifier); XCTAssertNotNil(createError); XCTAssertEqualObjects(createError.code, @"video_player"); } @@ -216,11 +216,11 @@ - (void)testBlankVideoBugWithEncryptedVideoStreamAndInvertedAspectRatioBugForSom formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(playerId); + XCTAssertNotNil(playerIdentifier); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); XCTAssertNotNil(player.playerLayer, @"AVPlayerLayer should be present."); @@ -292,15 +292,15 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&createError]; // Ensure that the video playback is paused before seeking. FlutterError *pauseError; - [videoPlayerPlugin pausePlayer:playerId.integerValue error:&pauseError]; + [videoPlayerPlugin pausePlayer:playerIdentifier.integerValue error:&pauseError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo completes"]; [videoPlayerPlugin seekTo:1234 - forPlayer:playerId.integerValue + forPlayer:playerIdentifier.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -309,7 +309,7 @@ - (void)testSeekToWhilePausedStartsDisplayLinkTemporarily { // Seeking to a new position should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersByIdentifier[playerIdentifier]; // Wait for the player's position to update, it shouldn't take long. XCTestExpectation *positionExpectation = [self expectationForPredicate:[NSPredicate predicateWithFormat:@"position == 1234"] @@ -364,7 +364,7 @@ - (void)testInitStartsDisplayLinkTemporarily { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&createError]; // Init should start the display link temporarily. OCMVerify([mockDisplayLink setRunning:YES]); @@ -380,7 +380,7 @@ - (void)testInitStartsDisplayLinkTemporarily { .andReturn(fakeBufferRef); // Simulate a callback from the engine to request a new frame. FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersByIdentifier[playerIdentifier]; [player copyPixelBuffer]; // Since a frame was found, and the video is paused, the display link should be paused again. OCMVerify([mockDisplayLink setRunning:NO]); @@ -416,15 +416,15 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&createError]; // Ensure that the video is playing before seeking. FlutterError *playError; - [videoPlayerPlugin playPlayer:playerId.integerValue error:&playError]; + [videoPlayerPlugin playPlayer:playerIdentifier.integerValue error:&playError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo completes"]; [videoPlayerPlugin seekTo:1234 - forPlayer:playerId.integerValue + forPlayer:playerIdentifier.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -432,7 +432,7 @@ - (void)testSeekToWhilePlayingDoesNotStopDisplayLink { OCMVerify([mockDisplayLink setRunning:YES]); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertEqual([player position], 1234); // Simulate a buffer being available. @@ -480,12 +480,12 @@ - (void)testPauseWhileWaitingForFrameDoesNotStopDisplayLink { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&createError]; // Run a play/pause cycle to force the pause codepath to run completely. FlutterError *playPauseError; - [videoPlayerPlugin playPlayer:playerId.integerValue error:&playPauseError]; - [videoPlayerPlugin pausePlayer:playerId.integerValue error:&playPauseError]; + [videoPlayerPlugin playPlayer:playerIdentifier.integerValue error:&playPauseError]; + [videoPlayerPlugin pausePlayer:playerIdentifier.integerValue error:&playPauseError]; // Since a buffer hasn't been available yet, the pause should not have stopped the display link. OCMVerify(never(), [mockDisplayLink setRunning:NO]); @@ -508,17 +508,17 @@ - (void)testDeregistersFromPlayer { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(playerId); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + XCTAssertNotNil(playerIdentifier); + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [self keyValueObservingExpectationForObject:avPlayer keyPath:@"currentItem" expectedValue:nil]; - [videoPlayerPlugin disposePlayer:playerId.integerValue error:&error]; - XCTAssertEqual(videoPlayerPlugin.playersById.count, 0); + [videoPlayerPlugin disposePlayer:playerIdentifier.integerValue error:&error]; + XCTAssertEqual(videoPlayerPlugin.playersByIdentifier.count, 0); XCTAssertNil(error); [self waitForExpectationsWithTimeout:30.0 handler:nil]; @@ -541,10 +541,10 @@ - (void)testBufferingStateFromPlayer { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(playerId); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + XCTAssertNotNil(playerIdentifier); + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); AVPlayer *avPlayer = player.player; [avPlayer play]; @@ -668,12 +668,12 @@ - (void)testSeekToleranceWhenNotSeekingToEnd { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo has zero tolerance when seeking not to end"]; [pluginWithMockAVPlayer seekTo:1234 - forPlayer:playerId.integerValue + forPlayer:playerIdentifier.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -707,13 +707,13 @@ - (void)testSeekToleranceWhenSeekingToEnd { httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; FlutterError *createError; - NSNumber *playerId = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; + NSNumber *playerIdentifier = [pluginWithMockAVPlayer createWithOptions:create error:&createError]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"seekTo has non-zero tolerance when seeking to end"]; // The duration of this video is "0" due to the non standard initiliatazion process. [pluginWithMockAVPlayer seekTo:0 - forPlayer:playerId.integerValue + forPlayer:playerIdentifier.integerValue completion:^(FlutterError *_Nullable error) { [initializedExpectation fulfill]; }]; @@ -735,9 +735,9 @@ - (void)testSeekToleranceWhenSeekingToEnd { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; @@ -759,15 +759,15 @@ - (void)testSeekToleranceWhenSeekingToEnd { XCTAssertEqual(avPlayer.timeControlStatus, AVPlayerTimeControlStatusPaused); // Change playback speed. - [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerIdentifier.integerValue error:&error]; XCTAssertNil(error); - [videoPlayerPlugin playPlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin playPlayer:playerIdentifier.integerValue error:&error]; XCTAssertNil(error); XCTAssertEqual(avPlayer.rate, 2); XCTAssertEqual(avPlayer.timeControlStatus, AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate); // Volume - [videoPlayerPlugin setVolume:0.1 forPlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin setVolume:0.1 forPlayer:playerIdentifier.integerValue error:&error]; XCTAssertNil(error); XCTAssertEqual(avPlayer.volume, 0.1f); @@ -803,16 +803,16 @@ - (void)testDoesNotCrashOnRateObservationAfterDisposal { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(playerId); + XCTAssertNotNil(playerIdentifier); - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); weakPlayer = player; avPlayer = player.player; - [videoPlayerPlugin disposePlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin disposePlayer:playerIdentifier.integerValue error:&error]; XCTAssertNil(error); } @@ -858,12 +858,12 @@ - (void)testHotReloadDoesNotCrash { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; XCTAssertNil(error); - XCTAssertNotNil(playerId); + XCTAssertNotNil(playerIdentifier); FVPTextureBasedVideoPlayer *player = - (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersById[playerId]; + (FVPTextureBasedVideoPlayer *)videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); weakPlayer = player; @@ -938,8 +938,8 @@ - (void)testFailedToLoadVideoEventShouldBeAlwaysSent { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTAssertNotNil(player); [self keyValueObservingExpectationForObject:(id)player.player.currentItem @@ -976,8 +976,8 @@ - (void)testUpdatePlayingStateShouldNotResetRate { formatHint:nil httpHeaders:@{} viewType:FVPPlatformVideoViewTypeTextureView]; - NSNumber *playerId = [videoPlayerPlugin createWithOptions:create error:&error]; - FVPVideoPlayer *player = videoPlayerPlugin.playersById[playerId]; + NSNumber *playerIdentifier = [videoPlayerPlugin createWithOptions:create error:&error]; + FVPVideoPlayer *player = videoPlayerPlugin.playersByIdentifier[playerIdentifier]; XCTestExpectation *initializedExpectation = [self expectationWithDescription:@"initialized"]; [player onListenWithArguments:nil @@ -988,8 +988,8 @@ - (void)testUpdatePlayingStateShouldNotResetRate { }]; [self waitForExpectationsWithTimeout:10 handler:nil]; - [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerId.integerValue error:&error]; - [videoPlayerPlugin playPlayer:playerId.integerValue error:&error]; + [videoPlayerPlugin setPlaybackSpeed:2 forPlayer:playerIdentifier.integerValue error:&error]; + [videoPlayerPlugin playPlayer:playerIdentifier.integerValue error:&error]; XCTAssertEqual(player.player.rate, 2); } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m index 435699879f1..e73d486da17 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPFrameUpdater.m @@ -25,7 +25,7 @@ - (void)displayLinkFired { CMTime outputItemTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; if ([self.videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { _lastKnownAvailableTime = outputItemTime; - [_registry textureFrameAvailable:_textureId]; + [_registry textureFrameAvailable:_textureIdentifier]; } } @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 3aeaa6fba20..7593c3e6d26 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -80,8 +80,8 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item return self; } -- (void)setTextureId:(int64_t)textureId { - self.frameUpdater.textureId = textureId; +- (void)setTextureIdentifier:(int64_t)textureIdentifier { + self.frameUpdater.textureIdentifier = textureIdentifier; } - (void)expectFrame { @@ -154,7 +154,7 @@ - (void)disposeSansEventChannel { - (void)dispose { [super dispose]; - _onDisposed(self.frameUpdater.textureId); + _onDisposed(self.frameUpdater.textureIdentifier); } #pragma mark - FlutterTexture 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 ae8f33bfc2f..1254ba6cceb 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 @@ -45,8 +45,8 @@ @interface FVPVideoPlayerPlugin () @property(readonly, strong, nonatomic) NSObject *registrar; @property(nonatomic, strong) id displayLinkFactory; @property(nonatomic, strong) id avFactory; -// TODO(stuartmorgan): Decouple IDs for platform views and texture views. -@property(nonatomic, assign) int64_t nextNonTexturePlayerId; +// TODO(stuartmorgan): Decouple identifiers for platform views and texture views. +@property(nonatomic, assign) int64_t nextNonTexturePlayerIdentifier; @end @implementation FVPVideoPlayerPlugin @@ -55,11 +55,11 @@ + (void)registerWithRegistrar:(NSObject *)registrar { [registrar publish:instance]; #if TARGET_OS_IOS // Platform views are only supported on iOS as of now. - FVPNativeVideoViewFactory *factory = - [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger - playerByIdProvider:^FVPVideoPlayer *(NSNumber *playerId) { - return instance->_playersById[playerId]; - }]; + FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] + initWithMessenger:registrar.messenger + playerByIdentifierProvider:^FVPVideoPlayer *(NSNumber *playerIdentifier) { + return instance->_playersByIdentifier[playerIdentifier]; + }]; [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; #endif SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); @@ -81,36 +81,37 @@ - (instancetype)initWithAVFactory:(id)avFactory _registrar = registrar; _displayLinkFactory = displayLinkFactory ?: [[FVPDefaultDisplayLinkFactory alloc] init]; _avFactory = avFactory ?: [[FVPDefaultAVFactory alloc] init]; - _playersById = [NSMutableDictionary dictionaryWithCapacity:1]; - // Initialized to a high number to avoid collisions with texture IDs (which are generated + _playersByIdentifier = [NSMutableDictionary dictionaryWithCapacity:1]; + // Initialized to a high number to avoid collisions with texture identifiers (which are generated // separately). - _nextNonTexturePlayerId = INT_MAX; + _nextNonTexturePlayerIdentifier = INT_MAX; return self; } - (void)detachFromEngineForRegistrar:(NSObject *)registrar { - [self.playersById.allValues makeObjectsPerformSelector:@selector(disposeSansEventChannel)]; - [self.playersById removeAllObjects]; + [self.playersByIdentifier.allValues + makeObjectsPerformSelector:@selector(disposeSansEventChannel)]; + [self.playersByIdentifier removeAllObjects]; SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, nil); } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player { BOOL textureBased = [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; - int64_t playerId; + int64_t playerIdentifier; if (textureBased) { - playerId = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; - [(FVPTextureBasedVideoPlayer *)player setTextureId:playerId]; + playerIdentifier = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; + [(FVPTextureBasedVideoPlayer *)player setTextureIdentifier:playerIdentifier]; } else { - playerId = self.nextNonTexturePlayerId--; + playerIdentifier = self.nextNonTexturePlayerIdentifier--; } FlutterEventChannel *eventChannel = [FlutterEventChannel - eventChannelWithName:[NSString - stringWithFormat:@"flutter.io/videoPlayer/videoEvents%lld", playerId] + eventChannelWithName:[NSString stringWithFormat:@"flutter.io/videoPlayer/videoEvents%lld", + playerIdentifier] binaryMessenger:_messenger]; [eventChannel setStreamHandler:player]; player.eventChannel = eventChannel; - self.playersById[@(playerId)] = player; + self.playersByIdentifier[@(playerIdentifier)] = player; if (textureBased) { // Ensure that the first frame is drawn once available, even if the video isn't played, since @@ -118,7 +119,7 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player { [(FVPTextureBasedVideoPlayer *)player expectFrame]; } - return playerId; + return playerIdentifier; } // This function, although slightly modified, is also in camera_avfoundation. @@ -163,8 +164,8 @@ - (void)initialize:(FlutterError *__autoreleasing *)error { upgradeAudioSessionCategory(AVAudioSessionCategoryPlayback, 0, 0); #endif - [self.playersById.allValues makeObjectsPerformSelector:@selector(dispose)]; - [self.playersById removeAllObjects]; + [self.playersByIdentifier.allValues makeObjectsPerformSelector:@selector(dispose)]; + [self.playersByIdentifier removeAllObjects]; } - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options @@ -201,8 +202,8 @@ - (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: }]; __weak typeof(self) weakSelf = self; - void (^onDisposed)(int64_t) = ^(int64_t textureId) { - [weakSelf.registry unregisterTexture:textureId]; + void (^onDisposed)(int64_t) = ^(int64_t textureIdentifier) { + [weakSelf.registry unregisterTexture:textureIdentifier]; }; if (options.asset) { @@ -254,42 +255,48 @@ - (NSString *)prepareAssetPathFromCreationOptions:(nonnull FVPCreationOptions *) return assetPath; } -- (void)disposePlayer:(NSInteger)playerId error:(FlutterError **)error { - NSNumber *playerKey = @(playerId); - FVPVideoPlayer *player = self.playersById[playerKey]; - [self.playersById removeObjectForKey:playerKey]; +- (void)disposePlayer:(NSInteger)playerIdentifier error:(FlutterError **)error { + NSNumber *playerKey = @(playerIdentifier); + FVPVideoPlayer *player = self.playersByIdentifier[playerKey]; + [self.playersByIdentifier removeObjectForKey:playerKey]; [player dispose]; } -- (void)setLooping:(BOOL)isLooping forPlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (void)setLooping:(BOOL)isLooping + forPlayer:(NSInteger)playerIdentifier + error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; player.isLooping = isLooping; } -- (void)setVolume:(double)volume forPlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (void)setVolume:(double)volume + forPlayer:(NSInteger)playerIdentifier + error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; [player setVolume:volume]; } -- (void)setPlaybackSpeed:(double)speed forPlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (void)setPlaybackSpeed:(double)speed + forPlayer:(NSInteger)playerIdentifier + error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; [player setPlaybackSpeed:speed]; } -- (void)playPlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (void)playPlayer:(NSInteger)playerIdentifier error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; [player play]; } -- (nullable NSNumber *)positionForPlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (nullable NSNumber *)positionForPlayer:(NSInteger)playerIdentifier error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; return @([player position]); } - (void)seekTo:(NSInteger)position - forPlayer:(NSInteger)playerId + forPlayer:(NSInteger)playerIdentifier completion:(nonnull void (^)(FlutterError *_Nullable))completion { - FVPVideoPlayer *player = self.playersById[@(playerId)]; + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; [player seekTo:position completionHandler:^(BOOL finished) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -298,8 +305,8 @@ - (void)seekTo:(NSInteger)position }]; } -- (void)pausePlayer:(NSInteger)playerId error:(FlutterError **)error { - FVPVideoPlayer *player = self.playersById[@(playerId)]; +- (void)pausePlayer:(NSInteger)playerIdentifier error:(FlutterError **)error { + FVPVideoPlayer *player = self.playersByIdentifier[@(playerIdentifier)]; [player pause]; } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h index 11f88dcbff2..9d5466d8757 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPFrameUpdater.h @@ -15,8 +15,8 @@ NS_ASSUME_NONNULL_BEGIN /// FVPFrameUpdater is responsible for notifying the Flutter texture registry /// when a new video frame is available. @interface FVPFrameUpdater : NSObject -/// The texture ID associated with the video output. -@property(nonatomic) int64_t textureId; +/// The texture identifier associated with the video output. +@property(nonatomic) int64_t textureIdentifier; /// The output that this updater is managing. @property(nonatomic, weak) AVPlayerItemVideoOutput *videoOutput; /// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index 4fae5713a0a..a2a89110748 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -18,7 +18,7 @@ /// Flutter app. @interface FVPNativeVideoViewFactory : NSObject /// Initializes a new instance of FVPNativeVideoViewFactory with the given messenger and -/// a block that provides video players associated with their IDs. +/// a block that provides video players associated with their identifiers. - (instancetype)initWithMessenger:(NSObject *)messenger - playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider; + playerByIdentifierProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdentifierProvider; @end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index c1c535e4245..88e4e400ce2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -32,9 +32,9 @@ NS_ASSUME_NONNULL_BEGIN registrar:(NSObject *)registrar onDisposed:(void (^)(int64_t))onDisposed; -/// Sets the texture ID for the frame updater. This method should be called once the texture ID is -/// obtained from the texture registry. -- (void)setTextureId:(int64_t)textureId; +/// Sets the texture Identifier for the frame updater. This method should be called once the texture +/// identifier is obtained from the texture registry. +- (void)setTextureIdentifier:(int64_t)textureIdentifier; /// Tells the player to run its frame updater until it receives a frame, regardless of the /// play/pause state. diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h index 3737f73e602..0c35429d026 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayerPlugin_Test.h @@ -19,7 +19,7 @@ @interface FVPVideoPlayerPlugin () @property(readonly, strong, nonatomic) - NSMutableDictionary *playersById; + NSMutableDictionary *playersByIdentifier; - (instancetype)initWithAVFactory:(id)avFactory displayLinkFactory:(id)displayLinkFactory diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m index 674c2fed346..94ece09e11e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m @@ -16,7 +16,7 @@ @interface FVPNativeVideoViewFactory () @implementation FVPNativeVideoViewFactory - (instancetype)initWithMessenger:(NSObject *)messenger - playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { + playerByIdentifierProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { self = [super init]; if (self) { _messenger = messenger; @@ -26,10 +26,10 @@ - (instancetype)initWithMessenger:(NSObject *)messenger } - (NSObject *)createWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId + viewIdentifier:(int64_t)viewIdentifier arguments:(FVPPlatformVideoViewCreationParams *)args { - NSNumber *playerId = @(args.playerId); - FVPVideoPlayer *player = self.playerByIdProvider(playerId); + NSNumber *playerIdentifier = @(args.playerId); + FVPVideoPlayer *player = self.playerByIdProvider(playerIdentifier); return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; } From b57d5f637f34f642f0ad56dab1666c1b7559efdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 10:57:40 +0100 Subject: [PATCH 158/167] Rename method according to Objective-C convention --- .../video_player_avfoundation/FVPTextureBasedVideoPlayer.m | 2 +- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 4 ++-- .../video_player_avfoundation/FVPVideoPlayer_Internal.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 7593c3e6d26..818dd336377 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -25,7 +25,7 @@ - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar onDisposed:(void (^)(int64_t))onDisposed { - return [self initWithURL:[NSURL fileURLWithPath:[self getAbsoluteAssetPath:asset]] + return [self initWithURL:[NSURL fileURLWithPath:[self absolutePathForAssetName:asset]] frameUpdater:frameUpdater displayLink:displayLink httpHeaders:@{} diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 0613f610424..25fd270e49e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -20,7 +20,7 @@ @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar { - return [self initWithURL:[NSURL fileURLWithPath:[self getAbsoluteAssetPath:asset]] + return [self initWithURL:[NSURL fileURLWithPath:[self absolutePathForAssetName:asset]] httpHeaders:@{} avFactory:avFactory registrar:registrar]; @@ -99,7 +99,7 @@ - (void)dealloc { } } -- (NSString *)getAbsoluteAssetPath:(NSString *)asset { +- (NSString *)absolutePathForAssetName:(NSString *)asset { NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; #if TARGET_OS_OSX // See https://github.com/flutter/flutter/issues/135302 diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h index 67443c6ef29..6824eefece2 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h @@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN /// Returns the absolute file path for a given asset name. /// This method attempts to locate the specified asset within the app bundle. -- (NSString *)getAbsoluteAssetPath:(NSString *)asset; +- (NSString *)absolutePathForAssetName:(NSString *)assetName; @end NS_ASSUME_NONNULL_END From c5b5170b7ecca356e3c20ada0179d7c0b44d290e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 10:59:48 +0100 Subject: [PATCH 159/167] Fix imports --- .../video_player_avfoundation/FVPTextureBasedVideoPlayer.m | 1 + .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 1 + .../video_player_avfoundation/FVPTextureBasedVideoPlayer.h | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index 818dd336377..afbeeee2783 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.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 "./include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h" #import "./include/video_player_avfoundation/FVPTextureBasedVideoPlayer_Test.h" @interface FVPTextureBasedVideoPlayer () diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 25fd270e49e..9dddf627e25 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.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 "./include/video_player_avfoundation/FVPVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Internal.h" #import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h index 88e4e400ce2..281438efe8d 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h @@ -4,6 +4,7 @@ #import "FVPDisplayLink.h" #import "FVPFrameUpdater.h" +#import "FVPVideoPlayer.h" #import "FVPVideoPlayer_Internal.h" NS_ASSUME_NONNULL_BEGIN From dae7fc4284f002313caf17c511e522148b3494a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:06:40 +0100 Subject: [PATCH 160/167] Restructure code to avoid additional casting --- .../FVPVideoPlayerPlugin.m | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 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 1254ba6cceb..581a4767a41 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 @@ -96,11 +96,15 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr } - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player { - BOOL textureBased = [player isKindOfClass:[FVPTextureBasedVideoPlayer class]]; + FVPTextureBasedVideoPlayer *textureBasedPlayer = + [player isKindOfClass:[FVPTextureBasedVideoPlayer class]] + ? (FVPTextureBasedVideoPlayer *)player + : nil; + int64_t playerIdentifier; - if (textureBased) { + if (textureBasedPlayer) { playerIdentifier = [self.registry registerTexture:(FVPTextureBasedVideoPlayer *)player]; - [(FVPTextureBasedVideoPlayer *)player setTextureIdentifier:playerIdentifier]; + [textureBasedPlayer setTextureIdentifier:playerIdentifier]; } else { playerIdentifier = self.nextNonTexturePlayerIdentifier--; } @@ -113,11 +117,9 @@ - (int64_t)onPlayerSetup:(FVPVideoPlayer *)player { player.eventChannel = eventChannel; self.playersByIdentifier[@(playerIdentifier)] = player; - if (textureBased) { - // Ensure that the first frame is drawn once available, even if the video isn't played, since - // the engine is now expecting the texture to be populated. - [(FVPTextureBasedVideoPlayer *)player expectFrame]; - } + // Ensure that the first frame is drawn once available, even if the video isn't played, since + // the engine is now expecting the texture to be populated. + [textureBasedPlayer expectFrame]; return playerIdentifier; } From 2b22477cecdc5af96e47eed0520779eb3fa13705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:08:14 +0100 Subject: [PATCH 161/167] Use ternary operator --- .../video_player_avfoundation/FVPVideoPlayerPlugin.m | 8 ++------ 1 file changed, 2 insertions(+), 6 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 581a4767a41..9e18460f166 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 @@ -175,12 +175,8 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options BOOL textureBased = options.viewType == FVPPlatformVideoViewTypeTextureView; @try { - FVPVideoPlayer *player; - if (textureBased) { - player = [self createTexturePlayerWithOptions:options]; - } else { - player = [self createPlatformViewPlayerWithOptions:options]; - } + FVPVideoPlayer *player = textureBased ? [self createTexturePlayerWithOptions:options] + : [self createPlatformViewPlayerWithOptions:options]; if (player == nil) { *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; From d4c6d8356e6b4bc5119fa3d9e321cb5a440a2c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:14:47 +0100 Subject: [PATCH 162/167] Remove verbs from naming in convenience constructors --- .../FVPVideoPlayerPlugin.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 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 9e18460f166..b48e4d065fe 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 @@ -175,8 +175,8 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options BOOL textureBased = options.viewType == FVPPlatformVideoViewTypeTextureView; @try { - FVPVideoPlayer *player = textureBased ? [self createTexturePlayerWithOptions:options] - : [self createPlatformViewPlayerWithOptions:options]; + FVPVideoPlayer *player = textureBased ? [self texturePlayerWithOptions:options] + : [self platformViewPlayerWithOptions:options]; if (player == nil) { *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; @@ -190,7 +190,7 @@ - (nullable NSNumber *)createWithOptions:(nonnull FVPCreationOptions *)options } } -- (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: +- (nullable FVPTextureBasedVideoPlayer *)texturePlayerWithOptions: (nonnull FVPCreationOptions *)options { FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc] initWithRegistry:_registry]; FVPDisplayLink *displayLink = @@ -205,7 +205,7 @@ - (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: }; if (options.asset) { - NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; + NSString *assetPath = [self assetPathFromCreationOptions:options]; return [[FVPTextureBasedVideoPlayer alloc] initWithAsset:assetPath frameUpdater:frameUpdater displayLink:displayLink @@ -225,11 +225,11 @@ - (nullable FVPTextureBasedVideoPlayer *)createTexturePlayerWithOptions: return nil; } -- (nullable FVPVideoPlayer *)createPlatformViewPlayerWithOptions: +- (nullable FVPVideoPlayer *)platformViewPlayerWithOptions: (nonnull FVPCreationOptions *)options { // FVPVideoPlayer contains all required logic for platform views. if (options.asset) { - NSString *assetPath = [self prepareAssetPathFromCreationOptions:options]; + NSString *assetPath = [self assetPathFromCreationOptions:options]; return [[FVPVideoPlayer alloc] initWithAsset:assetPath avFactory:_avFactory registrar:self.registrar]; @@ -243,7 +243,7 @@ - (nullable FVPVideoPlayer *)createPlatformViewPlayerWithOptions: return nil; } -- (NSString *)prepareAssetPathFromCreationOptions:(nonnull FVPCreationOptions *)options { +- (NSString *)assetPathFromCreationOptions:(nonnull FVPCreationOptions *)options { NSString *assetPath; if (options.packageName) { assetPath = [self.registrar lookupKeyForAsset:options.asset fromPackage:options.packageName]; From 91103eb471b9c8771bbb837aafd2fbf105866cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:15:53 +0100 Subject: [PATCH 163/167] Import Foundation instead of TargetConditionals --- .../video_player_avfoundation/FVPNativeVideoViewFactory.h | 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/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index a2a89110748..2872bebdfcf 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -4,7 +4,7 @@ // Platform views are only supported on iOS as of now. Ifdef is used to avoid compilation errors. -#import +#import #import "FVPVideoPlayer.h" From 615bad6e34c2503f3688d0b3c2d7c28380406221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:16:26 +0100 Subject: [PATCH 164/167] Document FVPVideoPlayer extension --- .../include/video_player_avfoundation/FVPVideoPlayer_Internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h index 6824eefece2..7e6e84eb415 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN +/// Interface intended for use by subclasses, but not other callers. @interface FVPVideoPlayer () /// The AVPlayerItemVideoOutput associated with this video player. @property(nonatomic, readonly) AVPlayerItemVideoOutput *videoOutput; From 31f0b1f5bb11f8a5f3e48713acd05e64081d2321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:33:08 +0100 Subject: [PATCH 165/167] Rename parameter --- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 9dddf627e25..f52cac90db9 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -100,8 +100,8 @@ - (void)dealloc { } } -- (NSString *)absolutePathForAssetName:(NSString *)asset { - NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; +- (NSString *)absolutePathForAssetName:(NSString *)assetName { + NSString *path = [[NSBundle mainBundle] pathForResource:assetName ofType:nil]; #if TARGET_OS_OSX // See https://github.com/flutter/flutter/issues/135302 // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. From 3b4fdb40b246ef0666d8278f79d6c3a3cb9fbea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 11:52:32 +0100 Subject: [PATCH 166/167] Use class method instead of instance method for helper --- .../video_player_avfoundation/FVPTextureBasedVideoPlayer.m | 2 +- .../Sources/video_player_avfoundation/FVPVideoPlayer.m | 6 +++--- .../video_player_avfoundation/FVPVideoPlayer_Internal.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m index afbeeee2783..509d0b5e55a 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPTextureBasedVideoPlayer.m @@ -26,7 +26,7 @@ - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar onDisposed:(void (^)(int64_t))onDisposed { - return [self initWithURL:[NSURL fileURLWithPath:[self absolutePathForAssetName:asset]] + return [self initWithURL:[NSURL fileURLWithPath:[FVPVideoPlayer absolutePathForAssetName:asset]] frameUpdater:frameUpdater displayLink:displayLink httpHeaders:@{} diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index f52cac90db9..d1d096e7b28 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -21,7 +21,7 @@ @implementation FVPVideoPlayer - (instancetype)initWithAsset:(NSString *)asset avFactory:(id)avFactory registrar:(NSObject *)registrar { - return [self initWithURL:[NSURL fileURLWithPath:[self absolutePathForAssetName:asset]] + return [self initWithURL:[NSURL fileURLWithPath:[FVPVideoPlayer absolutePathForAssetName:asset]] httpHeaders:@{} avFactory:avFactory registrar:registrar]; @@ -100,13 +100,13 @@ - (void)dealloc { } } -- (NSString *)absolutePathForAssetName:(NSString *)assetName { ++ (NSString *)absolutePathForAssetName:(NSString *)assetName { NSString *path = [[NSBundle mainBundle] pathForResource:assetName ofType:nil]; #if TARGET_OS_OSX // See https://github.com/flutter/flutter/issues/135302 // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. if (!path) { - path = [NSURL URLWithString:asset relativeToURL:NSBundle.mainBundle.bundleURL].path; + path = [NSURL URLWithString:assetName relativeToURL:NSBundle.mainBundle.bundleURL].path; } #endif diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h index 7e6e84eb415..995952de17e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer_Internal.h @@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN /// Returns the absolute file path for a given asset name. /// This method attempts to locate the specified asset within the app bundle. -- (NSString *)absolutePathForAssetName:(NSString *)assetName; ++ (NSString *)absolutePathForAssetName:(NSString *)assetName; @end NS_ASSUME_NONNULL_END From f1026ee8e4fbfe2b0479893d914b1f06b913bef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Fri, 7 Feb 2025 12:19:45 +0100 Subject: [PATCH 167/167] Format code --- .../Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m | 3 +-- 1 file changed, 1 insertion(+), 2 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 b48e4d065fe..1936435ffd0 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 @@ -225,8 +225,7 @@ - (nullable FVPTextureBasedVideoPlayer *)texturePlayerWithOptions: return nil; } -- (nullable FVPVideoPlayer *)platformViewPlayerWithOptions: - (nonnull FVPCreationOptions *)options { +- (nullable FVPVideoPlayer *)platformViewPlayerWithOptions:(nonnull FVPCreationOptions *)options { // FVPVideoPlayer contains all required logic for platform views. if (options.asset) { NSString *assetPath = [self assetPathFromCreationOptions:options];