@@ -23,13 +23,6 @@ @interface FVPFrameUpdater : NSObject
23
23
@property (nonatomic , weak ) AVPlayerItemVideoOutput *videoOutput;
24
24
// The last time that has been validated as avaliable according to hasNewPixelBufferForItemTime:.
25
25
@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;
33
26
@end
34
27
35
28
@implementation FVPFrameUpdater
@@ -42,18 +35,10 @@ - (FVPFrameUpdater *)initWithRegistry:(NSObject<FlutterTextureRegistry> *)regist
42
35
}
43
36
44
37
- (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;
57
42
[_registry textureFrameAvailable: _textureId];
58
43
}
59
44
}
@@ -334,10 +319,6 @@ - (instancetype)initWithPlayerItem:(AVPlayerItem *)item
334
319
};
335
320
_videoOutput = [avFactory videoOutputWithPixelBufferAttributes: pixBuffAttributes];
336
321
frameUpdater.videoOutput = _videoOutput;
337
- #if TARGET_OS_IOS
338
- // See TODO on this property in FVPFrameUpdater.
339
- frameUpdater.skipBufferAvailabilityCheck = YES ;
340
- #endif
341
322
342
323
[self addObserversForItem: item player: _player];
343
324
@@ -703,14 +684,10 @@ - (instancetype)initWithAVFactory:(id<FVPAVFactory>)avFactory
703
684
- (void )detachFromEngineForRegistrar : (NSObject <FlutterPluginRegistrar> *)registrar {
704
685
[self .playersByTextureId.allValues makeObjectsPerformSelector: @selector (disposeSansEventChannel )];
705
686
[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 );
710
688
}
711
689
712
- - (FVPTextureMessage *)onPlayerSetup : (FVPVideoPlayer *)player
713
- frameUpdater : (FVPFrameUpdater *)frameUpdater {
690
+ - (int64_t )onPlayerSetup : (FVPVideoPlayer *)player frameUpdater : (FVPFrameUpdater *)frameUpdater {
714
691
int64_t textureId = [self .registry registerTexture: player];
715
692
frameUpdater.textureId = textureId;
716
693
FlutterEventChannel *eventChannel = [FlutterEventChannel
@@ -725,8 +702,7 @@ - (FVPTextureMessage *)onPlayerSetup:(FVPVideoPlayer *)player
725
702
// the engine is now expecting the texture to be populated.
726
703
[player expectFrame ];
727
704
728
- FVPTextureMessage *result = [FVPTextureMessage makeWithTextureId: textureId];
729
- return result;
705
+ return textureId;
730
706
}
731
707
732
708
- (void )initialize : (FlutterError *__autoreleasing *)error {
@@ -743,7 +719,8 @@ - (void)initialize:(FlutterError *__autoreleasing *)error {
743
719
[self .playersByTextureId removeAllObjects ];
744
720
}
745
721
746
- - (FVPTextureMessage *)create : (FVPCreateMessage *)input error : (FlutterError **)error {
722
+ - (nullable NSNumber *)createWithOptions : (nonnull FVPCreationOptions *)options
723
+ error : (FlutterError **)error {
747
724
FVPFrameUpdater *frameUpdater = [[FVPFrameUpdater alloc ] initWithRegistry: _registry];
748
725
FVPDisplayLink *displayLink =
749
726
[self .displayLinkFactory displayLinkWithRegistrar: _registrar
@@ -752,110 +729,96 @@ - (FVPTextureMessage *)create:(FVPCreateMessage *)input error:(FlutterError **)e
752
729
}];
753
730
754
731
FVPVideoPlayer *player;
755
- if (input .asset ) {
732
+ if (options .asset ) {
756
733
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];
759
736
} else {
760
- assetPath = [_registrar lookupKeyForAsset: input .asset];
737
+ assetPath = [_registrar lookupKeyForAsset: options .asset];
761
738
}
762
739
@try {
763
740
player = [[FVPVideoPlayer alloc ] initWithAsset: assetPath
764
741
frameUpdater: frameUpdater
765
742
displayLink: displayLink
766
743
avFactory: _avFactory
767
744
registrar: self .registrar];
768
- return [self onPlayerSetup: player frameUpdater: frameUpdater];
745
+ return @( [self onPlayerSetup: player frameUpdater: frameUpdater]) ;
769
746
} @catch (NSException *exception) {
770
747
*error = [FlutterError errorWithCode: @" video_player" message: exception.reason details: nil ];
771
748
return nil ;
772
749
}
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]
775
752
frameUpdater: frameUpdater
776
753
displayLink: displayLink
777
- httpHeaders: input .httpHeaders
754
+ httpHeaders: options .httpHeaders
778
755
avFactory: _avFactory
779
756
registrar: self .registrar];
780
- return [self onPlayerSetup: player frameUpdater: frameUpdater];
757
+ return @( [self onPlayerSetup: player frameUpdater: frameUpdater]) ;
781
758
} else {
782
759
*error = [FlutterError errorWithCode: @" video_player" message: @" not implemented" details: nil ];
783
760
return nil ;
784
761
}
785
762
}
786
763
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);
789
766
FVPVideoPlayer *player = self.playersByTextureId [playerKey];
790
- [self .registry unregisterTexture: input. textureId];
767
+ [self .registry unregisterTexture: textureId];
791
768
[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
+ }
808
772
}
809
773
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;
813
777
}
814
778
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];
818
782
}
819
783
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];
823
787
}
824
788
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)];
827
791
[player play ];
828
792
}
829
793
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 ]);
835
797
}
836
798
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
841
804
completionHandler: ^(BOOL finished) {
842
805
dispatch_async (dispatch_get_main_queue (), ^{
843
806
completion (nil );
844
807
});
845
808
}];
846
809
}
847
810
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)];
850
813
[player pause ];
851
814
}
852
815
853
- - (void )setMixWithOthers : (FVPMixWithOthersMessage *) input
816
+ - (void )setMixWithOthers : (BOOL ) mixWithOthers
854
817
error : (FlutterError *_Nullable __autoreleasing *)error {
855
818
#if TARGET_OS_OSX
856
819
// AVAudioSession doesn't exist on macOS, and audio always mixes, so just no-op.
857
820
#else
858
- if (input. mixWithOthers ) {
821
+ if (mixWithOthers) {
859
822
[[AVAudioSession sharedInstance ] setCategory: AVAudioSessionCategoryPlayback
860
823
withOptions: AVAudioSessionCategoryOptionMixWithOthers
861
824
error: nil ];
0 commit comments