@@ -23,13 +23,6 @@ @interface FVPFrameUpdater : NSObject
2323@property (nonatomic , weak ) AVPlayerItemVideoOutput *videoOutput;
2424// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:.
2525@property (nonatomic , assign ) CMTime lastKnownAvailableTime;
26- // If YES, the engine is informed that a new texture is available any time the display link
27- // callback is fired, regardless of the videoOutput state.
28- //
29- // TODO(stuartmorgan): Investigate removing this; it exists only to preserve existing iOS behavior
30- // while implementing macOS, but iOS should very likely be doing the check as well. See
31- // https://github.com/flutter/flutter/issues/138427.
32- @property (nonatomic , assign ) BOOL skipBufferAvailabilityCheck;
3326@end
3427
3528@implementation FVPFrameUpdater
@@ -42,18 +35,10 @@ - (FVPFrameUpdater *)initWithRegistry:(NSObject<FlutterTextureRegistry> *)regist
4235}
4336
4437- (void )displayLinkFired {
45- // Only report a new frame if one is actually available, or the check is being skipped.
46- BOOL reportFrame = NO ;
47- if (self.skipBufferAvailabilityCheck ) {
48- reportFrame = YES ;
49- } else {
50- CMTime outputItemTime = [self .videoOutput itemTimeForHostTime: CACurrentMediaTime ()];
51- if ([self .videoOutput hasNewPixelBufferForItemTime: outputItemTime]) {
52- _lastKnownAvailableTime = outputItemTime;
53- reportFrame = YES ;
54- }
55- }
56- if (reportFrame) {
38+ // Only report a new frame if one is actually available.
39+ CMTime outputItemTime = [self .videoOutput itemTimeForHostTime: CACurrentMediaTime ()];
40+ if ([self .videoOutput hasNewPixelBufferForItemTime: outputItemTime]) {
41+ _lastKnownAvailableTime = outputItemTime;
5742 [_registry textureFrameAvailable: _textureId];
5843 }
5944}
@@ -334,10 +319,6 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item
334319 };
335320 _videoOutput = [avFactory videoOutputWithPixelBufferAttributes: pixBuffAttributes];
336321 frameUpdater.videoOutput = _videoOutput;
337- #if TARGET_OS_IOS
338- // See TODO on this property in FVPFrameUpdater.
339- frameUpdater.skipBufferAvailabilityCheck = YES ;
340- #endif
341322
342323 [self addObserversForItem: item player: _player];
343324
@@ -703,14 +684,10 @@ - (instancetype)initWithAVFactory:(id<FVPAVFactory>)avFactory
703684- (void )detachFromEngineForRegistrar : (NSObject <FlutterPluginRegistrar> *)registrar {
704685 [self .playersByTextureId.allValues makeObjectsPerformSelector: @selector (disposeSansEventChannel )];
705686 [self .playersByTextureId removeAllObjects ];
706- // TODO(57151): This should be commented out when 57151's fix lands on stable.
707- // This is the correct behavior we never did it in the past and the engine
708- // doesn't currently support it.
709- // FVPAVFoundationVideoPlayerApiSetup(registrar.messenger, nil);
687+ SetUpFVPAVFoundationVideoPlayerApi (registrar.messenger , nil );
710688}
711689
712- - (FVPTextureMessage *)onPlayerSetup : (FVPVideoPlayer *)player
713- frameUpdater : (FVPFrameUpdater *)frameUpdater {
690+ - (int64_t )onPlayerSetup : (FVPVideoPlayer *)player frameUpdater : (FVPFrameUpdater *)frameUpdater {
714691 int64_t textureId = [self .registry registerTexture: player];
715692 frameUpdater.textureId = textureId;
716693 FlutterEventChannel *eventChannel = [FlutterEventChannel
@@ -725,8 +702,7 @@ - (FVPTextureMessage *)onPlayerSetup:(FVPVideoPlayer *)player
725702 // the engine is now expecting the texture to be populated.
726703 [player expectFrame ];
727704
728- FVPTextureMessage *result = [FVPTextureMessage makeWithTextureId: textureId];
729- return result;
705+ return textureId;
730706}
731707
732708- (void )initialize : (FlutterError *__autoreleasing *)error {
@@ -743,7 +719,8 @@ - (void)initialize:(FlutterError *__autoreleasing *)error {
743719 [self .playersByTextureId removeAllObjects ];
744720}
745721
746- - (FVPTextureMessage *)create : (FVPCreateMessage *)input error : (FlutterError **)error {
722+ - (nullable NSNumber *)createWithOptions : (nonnull FVPCreationOptions *)options
723+ error : (FlutterError **)error {
747724 FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc ] initWithRegistry: _registry];
748725 FVPDisplayLink *displayLink =
749726 [self .displayLinkFactory displayLinkWithRegistrar: _registrar
@@ -752,110 +729,96 @@ - (FVPTextureMessage *)create:(FVPCreateMessage *)input error:(FlutterError **)e
752729 }];
753730
754731 FVPVideoPlayer *player;
755- if (input .asset ) {
732+ if (options .asset ) {
756733 NSString *assetPath;
757- if (input .packageName ) {
758- assetPath = [_registrar lookupKeyForAsset: input .asset fromPackage: input .packageName];
734+ if (options .packageName ) {
735+ assetPath = [_registrar lookupKeyForAsset: options .asset fromPackage: options .packageName];
759736 } else {
760- assetPath = [_registrar lookupKeyForAsset: input .asset];
737+ assetPath = [_registrar lookupKeyForAsset: options .asset];
761738 }
762739 @try {
763740 player = [[FVPVideoPlayer alloc ] initWithAsset: assetPath
764741 frameUpdater: frameUpdater
765742 displayLink: displayLink
766743 avFactory: _avFactory
767744 registrar: self .registrar];
768- return [self onPlayerSetup: player frameUpdater: frameUpdater];
745+ return @( [self onPlayerSetup: player frameUpdater: frameUpdater]) ;
769746 } @catch (NSException *exception) {
770747 *error = [FlutterError errorWithCode: @" video_player" message: exception.reason details: nil ];
771748 return nil ;
772749 }
773- } else if (input .uri ) {
774- player = [[FVPVideoPlayer alloc ] initWithURL: [NSURL URLWithString: input .uri]
750+ } else if (options .uri ) {
751+ player = [[FVPVideoPlayer alloc ] initWithURL: [NSURL URLWithString: options .uri]
775752 frameUpdater: frameUpdater
776753 displayLink: displayLink
777- httpHeaders: input .httpHeaders
754+ httpHeaders: options .httpHeaders
778755 avFactory: _avFactory
779756 registrar: self .registrar];
780- return [self onPlayerSetup: player frameUpdater: frameUpdater];
757+ return @( [self onPlayerSetup: player frameUpdater: frameUpdater]) ;
781758 } else {
782759 *error = [FlutterError errorWithCode: @" video_player" message: @" not implemented" details: nil ];
783760 return nil ;
784761 }
785762}
786763
787- - (void )dispose : (FVPTextureMessage *) input error : (FlutterError **)error {
788- NSNumber *playerKey = @(input. textureId );
764+ - (void )disposePlayer : ( NSInteger ) textureId error : (FlutterError **)error {
765+ NSNumber *playerKey = @(textureId);
789766 FVPVideoPlayer *player = self.playersByTextureId [playerKey];
790- [self .registry unregisterTexture: input. textureId];
767+ [self .registry unregisterTexture: textureId];
791768 [self .playersByTextureId removeObjectForKey: playerKey];
792- // If the Flutter contains https://github.com/flutter/engine/pull/12695,
793- // the `player` is disposed via `onTextureUnregistered` at the right time.
794- // Without https://github.com/flutter/engine/pull/12695, there is no guarantee that the
795- // texture has completed the un-reregistration. It may leads a crash if we dispose the
796- // `player` before the texture is unregistered. We add a dispatch_after hack to make sure the
797- // texture is unregistered before we dispose the `player`.
798- //
799- // TODO(cyanglaz): Remove this dispatch block when
800- // https://github.com/flutter/flutter/commit/8159a9906095efc9af8b223f5e232cb63542ad0b is in
801- // stable And update the min flutter version of the plugin to the stable version.
802- dispatch_after (dispatch_time (DISPATCH_TIME_NOW, (int64_t )(1 * NSEC_PER_SEC)),
803- dispatch_get_main_queue (), ^{
804- if (!player.disposed ) {
805- [player dispose ];
806- }
807- });
769+ if (!player.disposed ) {
770+ [player dispose ];
771+ }
808772}
809773
810- - (void )setLooping : (FVPLoopingMessage *) input error : (FlutterError **)error {
811- FVPVideoPlayer *player = self.playersByTextureId [@(input. textureId)];
812- player.isLooping = input. isLooping ;
774+ - (void )setLooping : (BOOL ) isLooping forPlayer : ( NSInteger ) textureId error : (FlutterError **)error {
775+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
776+ player.isLooping = isLooping;
813777}
814778
815- - (void )setVolume : (FVPVolumeMessage *) input error : (FlutterError **)error {
816- FVPVideoPlayer *player = self.playersByTextureId [@(input. textureId)];
817- [player setVolume: input. volume];
779+ - (void )setVolume : (double ) volume forPlayer : ( NSInteger ) textureId error : (FlutterError **)error {
780+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
781+ [player setVolume: volume];
818782}
819783
820- - (void )setPlaybackSpeed : (FVPPlaybackSpeedMessage *) input error : (FlutterError **)error {
821- FVPVideoPlayer *player = self.playersByTextureId [@(input. textureId)];
822- [player setPlaybackSpeed: input. speed];
784+ - (void )setPlaybackSpeed : (double ) speed forPlayer : ( NSInteger ) textureId error : (FlutterError **)error {
785+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
786+ [player setPlaybackSpeed: speed];
823787}
824788
825- - (void )play : (FVPTextureMessage *) input error : (FlutterError **)error {
826- FVPVideoPlayer *player = self.playersByTextureId [@(input. textureId)];
789+ - (void )playPlayer : ( NSInteger ) textureId error : (FlutterError **)error {
790+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
827791 [player play ];
828792}
829793
830- - (FVPPositionMessage *)position : (FVPTextureMessage *)input error : (FlutterError **)error {
831- FVPVideoPlayer *player = self.playersByTextureId [@(input.textureId)];
832- FVPPositionMessage *result = [FVPPositionMessage makeWithTextureId: input.textureId
833- position: [player position ]];
834- return result;
794+ - (nullable NSNumber *)positionForPlayer : (NSInteger )textureId error : (FlutterError **)error {
795+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
796+ return @([player position ]);
835797}
836798
837- - (void )seekTo : (FVPPositionMessage *)input
838- completion : (void (^)(FlutterError *_Nullable))completion {
839- FVPVideoPlayer *player = self.playersByTextureId [@(input.textureId)];
840- [player seekTo: input.position
799+ - (void )seekTo : (NSInteger )position
800+ forPlayer : (NSInteger )textureId
801+ completion : (nonnull void (^)(FlutterError *_Nullable))completion {
802+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
803+ [player seekTo: position
841804 completionHandler: ^(BOOL finished) {
842805 dispatch_async (dispatch_get_main_queue (), ^{
843806 completion (nil );
844807 });
845808 }];
846809}
847810
848- - (void )pause : (FVPTextureMessage *) input error : (FlutterError **)error {
849- FVPVideoPlayer *player = self.playersByTextureId [@(input. textureId)];
811+ - (void )pausePlayer : ( NSInteger ) textureId error : (FlutterError **)error {
812+ FVPVideoPlayer *player = self.playersByTextureId [@(textureId)];
850813 [player pause ];
851814}
852815
853- - (void )setMixWithOthers : (FVPMixWithOthersMessage *) input
816+ - (void )setMixWithOthers : (BOOL ) mixWithOthers
854817 error : (FlutterError *_Nullable __autoreleasing *)error {
855818#if TARGET_OS_OSX
856819 // AVAudioSession doesn't exist on macOS, and audio always mixes, so just no-op.
857820#else
858- if (input. mixWithOthers ) {
821+ if (mixWithOthers) {
859822 [[AVAudioSession sharedInstance ] setCategory: AVAudioSessionCategoryPlayback
860823 withOptions: AVAudioSessionCategoryOptionMixWithOthers
861824 error: nil ];
0 commit comments