IosTexturePlugin.m 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #import "IosTexturePlugin.h"
  2. #import <CoreVideo/CoreVideo.h>
  3. #import "OralCavityManager.h"
  4. #define WeakSelf __weak typeof(self) weakSelf = self;
  5. //FlutterTexture
  6. @interface MyTexture : NSObject <FlutterTexture>
  7. @property(nonatomic, assign) CVPixelBufferRef pixelBuffer;
  8. @end
  9. @implementation MyTexture
  10. // Flutter 会调用此方法来获取 CVPixelBuffer
  11. - (CVPixelBufferRef)copyPixelBuffer {
  12. //3.
  13. if (_pixelBuffer) {
  14. // CVPixelBufferRetain(_pixelBuffer);
  15. return _pixelBuffer;
  16. }
  17. return NULL;
  18. }
  19. // 你需要在不再需要 pixelBuffer 时释放它
  20. - (void)dealloc {
  21. if (_pixelBuffer) {
  22. CVPixelBufferRelease(_pixelBuffer);
  23. }
  24. }
  25. @end
  26. //FlutterPlatformView
  27. @interface MyCustomView : NSObject<FlutterPlatformView>
  28. - (instancetype)initWithFrame:(CGRect)frame view:(CALayer *)view;
  29. @end
  30. @implementation MyCustomView {
  31. UIView *_view;
  32. }
  33. - (instancetype)initWithFrame:(CGRect)frame view:(CALayer *)view {
  34. self = [super init];
  35. if (self) {
  36. _view = [[UIView alloc] initWithFrame:frame];
  37. [_view.layer addSublayer:view];
  38. }
  39. return self;
  40. }
  41. - (UIView*)view {
  42. return _view;
  43. }
  44. @end
  45. //FlutterPlatformViewFactory
  46. @interface MyCustomViewFactory : NSObject<FlutterPlatformViewFactory>
  47. @property(nonatomic, strong) CALayer * videoView;
  48. @end
  49. @implementation MyCustomViewFactory
  50. - (nonnull NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame
  51. viewIdentifier:(int64_t)viewId
  52. arguments:(id _Nullable)args {
  53. return [[MyCustomView alloc] initWithFrame:frame view:_videoView];
  54. }
  55. @end
  56. @interface IosTexturePlugin ()
  57. @property(nonatomic, strong) MyTexture *myTexture;
  58. @property(nonatomic, strong) NSObject<FlutterTextureRegistry> *textureRegistry;
  59. @property(nonatomic, assign) int64_t textureId;
  60. @property (nonatomic, strong) FlutterMethodChannel *videoControlChannel;
  61. @end
  62. @implementation IosTexturePlugin
  63. + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  64. //视频控制
  65. FlutterMethodChannel* videoControlChannel = [FlutterMethodChannel
  66. methodChannelWithName:@"videoControl"
  67. binaryMessenger:[registrar messenger]];
  68. //文件控制
  69. FlutterMethodChannel* fileControlChannel = [FlutterMethodChannel
  70. methodChannelWithName:@"fileControl"
  71. binaryMessenger:[registrar messenger]];
  72. IosTexturePlugin* instance = [[IosTexturePlugin alloc] initWithRegistrar:registrar Channel:videoControlChannel];
  73. [registrar addMethodCallDelegate:instance channel:videoControlChannel];
  74. [registrar addMethodCallDelegate:instance channel:fileControlChannel];
  75. //视频流
  76. [OralCavityManager sharedInstance].getVideoView = ^(CALayer *view) {
  77. MyCustomViewFactory* factory = [[MyCustomViewFactory alloc] init];
  78. factory.videoView = view;
  79. [registrar registerViewFactory:factory withId:@"VideoView"];
  80. };
  81. //设备拍照
  82. [OralCavityManager sharedInstance].onDeviceTakePhoto = ^{
  83. //sendToflutter
  84. NSLog(@"===onDeviceTakePhoto");
  85. [videoControlChannel invokeMethod:@"onDeviceTakePhoto" arguments:nil];
  86. };
  87. }
  88. - (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar Channel:(FlutterMethodChannel *)videoControlChannel {
  89. self = [super init];
  90. if (self) {
  91. _textureRegistry = [registrar textures];
  92. _myTexture = [[MyTexture alloc] init];
  93. // 注册纹理并获取纹理ID
  94. _textureId = [_textureRegistry registerTexture:_myTexture];
  95. //设置回调channel
  96. _videoControlChannel = videoControlChannel;
  97. }
  98. return self;
  99. }
  100. - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  101. WeakSelf;
  102. //获取设备连接状态
  103. if ([@"getConnectStatus" isEqualToString:call.method]) {
  104. // NSLog(@"获取状态 === %d", [[OralCavityManager sharedInstance] connectToServer]);
  105. result(@([[OralCavityManager sharedInstance] connectToServer]));
  106. }
  107. //开始视频
  108. else if ([@"startVideo" isEqualToString:call.method]) {
  109. NSLog(@"开始视频textureId === %lld",self.textureId);
  110. result(@(self.textureId));
  111. [[OralCavityManager sharedInstance] startVideo];
  112. // [OralCavityManager sharedInstance].getPixelBuffer = ^(CVPixelBufferRef pixelBuffer) {
  113. //
  114. // if (pixelBuffer) {
  115. // // 在赋值之前释放旧的 pixel buffer,避免内存泄漏
  116. // if (weakSelf.myTexture.pixelBuffer != NULL) {
  117. // CVPixelBufferRelease(weakSelf.myTexture.pixelBuffer);
  118. // }
  119. //
  120. // // 保留新获取的 pixel buffer,确保它不会被释放
  121. // CVPixelBufferRetain(pixelBuffer);
  122. // weakSelf.myTexture.pixelBuffer = pixelBuffer;
  123. //
  124. // // 通知 Flutter 有新帧可以显示
  125. // [weakSelf.textureRegistry textureFrameAvailable:weakSelf.textureId];
  126. // }
  127. //
  128. // };
  129. }
  130. //停止视频
  131. else if ([@"stopVideo" isEqualToString:call.method]) {
  132. NSLog(@"===停止视频");
  133. [[OralCavityManager sharedInstance] stopVideo];
  134. }
  135. //拍照
  136. else if ([@"takePhoto" isEqualToString:call.method]) {
  137. NSLog(@"===拍照 %@",call.arguments);
  138. [[OralCavityManager sharedInstance] takePhoto:call.arguments];
  139. [OralCavityManager sharedInstance].getPhotoPath = ^(NSString *path) {
  140. if ([path containsString:@"jpg"]) {
  141. result(path);
  142. }else {
  143. result([FlutterError errorWithCode:call.method message:path details:@"appId"]);
  144. }
  145. NSLog(@"拍照结果photoPath ===%@",path);
  146. };
  147. }
  148. //savePhoto
  149. else if([@"savePhoto" isEqualToString:call.method]) {
  150. NSLog(@"savePhoto ===arguments %@",call.arguments);
  151. [[OralCavityManager sharedInstance] savePhoto:call.arguments];
  152. [OralCavityManager sharedInstance].getSavePhotoPath = ^(NSString *path) {
  153. if ([path containsString:@"error"]) {
  154. result([FlutterError errorWithCode:call.method message:path details:@"appId"]);
  155. }else {
  156. result(path);
  157. }
  158. NSLog(@"savePhoto ===%@",path);
  159. };
  160. }
  161. //开始录像
  162. else if ([@"startRecord" isEqualToString:call.method]) {
  163. NSLog(@"===开始录像 %@",call.arguments);
  164. [[OralCavityManager sharedInstance] startRecord:call.arguments];
  165. result(@"startRecord");
  166. }
  167. //停止录像
  168. else if ([@"stopRecord" isEqualToString:call.method]) {
  169. [[OralCavityManager sharedInstance] stopRecord];
  170. [OralCavityManager sharedInstance].getVideoPath = ^(NSString *path) {
  171. if ([path containsString:@"Documents"]) {
  172. result(path);
  173. }else {
  174. result([FlutterError errorWithCode:call.method message:path details:@"appId"]);
  175. }
  176. NSLog(@"停止录像VideoPath ===%@",path);
  177. };
  178. }
  179. //saveRecord
  180. else if([@"saveRecord" isEqualToString:call.method]) {
  181. NSLog(@"saveRecord ===arguments %@",call.arguments);
  182. [[OralCavityManager sharedInstance] saveRecord:call.arguments];
  183. [OralCavityManager sharedInstance].getSaveRecordPath = ^(NSString *path) {
  184. if ([path containsString:@"error"]) {
  185. result([FlutterError errorWithCode:call.method message:path details:@"appId"]);
  186. }else {
  187. result(path);
  188. }
  189. NSLog(@"saveRecord ===%@",path);
  190. };
  191. }
  192. //获取图片列表
  193. else if ([@"getPhotoList" isEqualToString:call.method]) {
  194. NSArray * arr = [[OralCavityManager sharedInstance] getPhotoList];
  195. // if (arr.count > 0) {
  196. result(arr);
  197. // }else {
  198. // result([FlutterError errorWithCode:call.method message:@"获取图片列表失败" details:@"appId"]);
  199. // }
  200. NSLog(@"===photolist = %@",arr);
  201. }
  202. //获取视频列表
  203. else if ([@"getVideoList" isEqualToString:call.method]) {
  204. NSArray *arr = [[OralCavityManager sharedInstance] getVideoList];
  205. // if (arr.count > 0) {
  206. result(arr);
  207. // }else {
  208. // result([FlutterError errorWithCode:call.method message:@"获取视频列表失败" details:@"appId"]);
  209. // }
  210. NSLog(@"===videoList = %@",arr);
  211. }
  212. //删除指定文件
  213. else if ([@"deleteFile" isEqualToString:call.method]) {
  214. NSLog(@"===deleteFile = %@",call.arguments);
  215. int success = [[OralCavityManager sharedInstance] deleteFile:call.arguments];
  216. result(@(success));
  217. }
  218. //横屏
  219. else if ([@"getLandscapeView" isEqualToString:call.method]) {
  220. NSArray *arr = call.arguments;
  221. NSLog(@"===fullScreen %@",arr);
  222. [[OralCavityManager sharedInstance] getLandscapeView:arr];
  223. }
  224. //竖屏
  225. else if ([@"getPortraitView" isEqualToString:call.method]) {
  226. NSLog(@"===smallScreen");
  227. [[OralCavityManager sharedInstance] getPortraitView];
  228. }
  229. else {
  230. result(FlutterMethodNotImplemented);
  231. }
  232. }
  233. @end