FlutterIJK.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // Created by Caijinglong on 2019-03-08.
  3. //
  4. #import "FlutterIJK.h"
  5. #import <IJKMediaFramework/IJKMediaFramework.h>
  6. #import <IJKMediaFramework/IJKMediaPlayer.h>
  7. #import <AVFoundation/AVFoundation.h>
  8. #import <libkern/OSAtomic.h>
  9. @interface FlutterIJK () <FlutterTexture>
  10. @end
  11. @implementation FlutterIJK {
  12. int64_t textureId;
  13. CADisplayLink *displayLink;
  14. NSObject <FlutterTextureRegistry> *textures;
  15. IJKFFMoviePlayerController *controller;
  16. CVPixelBufferRef latestPixelBuffer;
  17. FlutterMethodChannel *channel;
  18. FlutterMethodCallHandler handler;
  19. }
  20. - (instancetype)initWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
  21. self = [super init];
  22. if (self) {
  23. self.registrar = registrar;
  24. textures = [self.registrar textures];
  25. textureId = [textures registerTexture:self];
  26. NSString *channelName = [NSString stringWithFormat:@"top.kikt/ijkplayer/%lli", textureId];
  27. channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:[registrar messenger]];
  28. [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
  29. [self handleMethodCall:call result:result];
  30. }];
  31. }
  32. return self;
  33. }
  34. - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
  35. if ([@"play" isEqualToString:call.method]) {
  36. [self play];
  37. } else if ([@"pause" isEqualToString:call.method]) {
  38. [self pause];
  39. } else if ([@"stop" isEqualToString:call.method]) {
  40. [self stop];
  41. } else if ([@"setDataSource" isEqualToString:call.method]) {
  42. @try {
  43. NSDictionary *params = call.arguments;
  44. NSString *uri = params[@"uri"];
  45. [self setDateSourceWithUri:uri];
  46. result(nil);
  47. }
  48. @catch (NSException *exception) {
  49. NSLog(@"Exception occurred: %@, %@", exception, [exception userInfo]);
  50. result([FlutterError errorWithCode:@"1" message:@"设置失败" details:nil]);
  51. }
  52. }
  53. }
  54. + (instancetype)ijkWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
  55. return [[self alloc] initWithRegistrar:registrar];
  56. }
  57. - (int64_t)id {
  58. return textureId;
  59. }
  60. - (void)dispose {
  61. [[self.registrar textures]unregisterTexture:self.id];
  62. [controller stop];
  63. [controller shutdown];
  64. controller = nil;
  65. displayLink.paused = YES;
  66. [displayLink invalidate];
  67. }
  68. - (void)play {
  69. [controller play];
  70. }
  71. - (void)pause {
  72. [controller pause];
  73. }
  74. - (void)stop {
  75. [controller stop];
  76. }
  77. - (void)setDateSourceWithUri:(NSString *)uri {
  78. IJKFFOptions *options = [IJKFFOptions optionsByDefault];
  79. controller = [[IJKFFMoviePlayerController alloc] initWithContentURLString:uri withOptions:options];
  80. [controller prepareToPlay];
  81. displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)];
  82. [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
  83. displayLink.paused = YES;
  84. }
  85. - (void)onDisplayLink:(CADisplayLink *)link {
  86. [textures textureFrameAvailable:textureId];
  87. }
  88. - (CVPixelBufferRef _Nullable)copyPixelBuffer {
  89. CVPixelBufferRef newBuffer = [controller framePixelbuffer];
  90. if (newBuffer) {
  91. CFRetain(newBuffer);
  92. CVPixelBufferRef pixelBuffer = latestPixelBuffer;
  93. while (!OSAtomicCompareAndSwapPtrBarrier(pixelBuffer, newBuffer, (void **) &latestPixelBuffer)) {
  94. pixelBuffer = latestPixelBuffer;
  95. }
  96. return pixelBuffer;
  97. }
  98. return NULL;
  99. }
  100. @end