// // Created by Caijinglong on 2019-03-08. // #import "FlutterIJK.h" #import #import #import #import @interface FlutterIJK () @end @implementation FlutterIJK { int64_t textureId; CADisplayLink *displayLink; NSObject *textures; IJKFFMoviePlayerController *controller; CVPixelBufferRef latestPixelBuffer; FlutterMethodChannel *channel; FlutterMethodCallHandler handler; } - (instancetype)initWithRegistrar:(NSObject *)registrar { self = [super init]; if (self) { self.registrar = registrar; textures = [self.registrar textures]; textureId = [textures registerTexture:self]; NSString *channelName = [NSString stringWithFormat:@"top.kikt/ijkplayer/%lli", textureId]; channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:[registrar messenger]]; [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { [self handleMethodCall:call result:result]; }]; } return self; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"play" isEqualToString:call.method]) { [self play]; } else if ([@"pause" isEqualToString:call.method]) { [self pause]; } else if ([@"stop" isEqualToString:call.method]) { [self stop]; } else if ([@"setNetworkDataSource" isEqualToString:call.method]) { @try { NSDictionary *params = call.arguments; NSString *uri = params[@"uri"]; [self setDataSourceWithUri:uri]; result(nil); } @catch (NSException *exception) { NSLog(@"Exception occurred: %@, %@", exception, [exception userInfo]); result([FlutterError errorWithCode:@"1" message:@"设置失败" details:nil]); } } else if ([@"setAssetDataSource" isEqualToString:call.method]) { @try { NSDictionary *params = [call arguments]; NSString *name = params[@"name"]; NSString *pkg = params[@"package"]; IJKFFMoviePlayerController *playerController = [self createControllerWithAssetName:name pkg:pkg]; [self setDataSourceWithController:playerController]; result(nil); } @catch (NSException *exception) { NSLog(@"Exception occurred: %@, %@", exception, [exception userInfo]); result([FlutterError errorWithCode:@"1" message:@"设置失败" details:nil]); } } else if ([@"setFileDataSource" isEqualToString:call.method]) { NSDictionary *params = call.arguments; NSString *path = params[@"path"]; IJKFFMoviePlayerController *playerController = [self createControllerWithPath:path]; } else { result(FlutterMethodNotImplemented); } } + (instancetype)ijkWithRegistrar:(NSObject *)registrar { return [[self alloc] initWithRegistrar:registrar]; } - (int64_t)id { return textureId; } - (void)dispose { [[self.registrar textures]unregisterTexture:self.id]; [controller stop]; [controller shutdown]; controller = nil; displayLink.paused = YES; [displayLink invalidate]; } - (void)play { [controller play]; } - (void)pause { [controller pause]; } - (void)stop { [controller stop]; } - (void)setDataSourceWithController:(IJKFFMoviePlayerController *)ctl { if (ctl) { controller = ctl; [self prepare]; } } - (IJKFFOptions *)createOption { IJKFFOptions *options = [IJKFFOptions optionsByDefault]; return options; } - (void)setDataSourceWithUri:(NSString *)uri { IJKFFOptions *options = [self createOption]; controller = [[IJKFFMoviePlayerController alloc] initWithContentURLString:uri withOptions:options]; [self prepare]; } - (void)prepare { [controller prepareToPlay]; if (displayLink) { displayLink.paused = YES; [displayLink invalidate]; displayLink = nil; } displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)]; [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; displayLink.paused = YES; } - (IJKFFMoviePlayerController *)createControllerWithAssetName:(NSString *)assetName pkg:(NSString *)pkg { NSString *asset; if (!pkg) { asset = [self.registrar lookupKeyForAsset:assetName]; } else { asset = [self.registrar lookupKeyForAsset:assetName fromPackage:pkg]; } NSString *path = [[NSBundle mainBundle] pathForResource:asset ofType:nil]; NSURL *url = [NSURL fileURLWithPath:path]; IJKFFOptions *options = [self createOption]; return [[IJKFFMoviePlayerController alloc] initWithContentURL:url withOptions:options]; } - (IJKFFMoviePlayerController *)createControllerWithPath:(NSString *)path { NSURL *url = [NSURL fileURLWithPath:path]; IJKFFOptions *options = [self createOption]; return [[IJKFFMoviePlayerController alloc] initWithContentURL:url withOptions:options]; } - (void)onDisplayLink:(CADisplayLink *)link { [textures textureFrameAvailable:textureId]; } - (CVPixelBufferRef _Nullable)copyPixelBuffer { CVPixelBufferRef newBuffer = [controller framePixelbuffer]; if (newBuffer) { CFRetain(newBuffer); CVPixelBufferRef pixelBuffer = latestPixelBuffer; while (!OSAtomicCompareAndSwapPtrBarrier(pixelBuffer, newBuffer, (void **) &latestPixelBuffer)) { pixelBuffer = latestPixelBuffer; } return pixelBuffer; } return NULL; } @end