controller_old.dart 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. import 'dart:async';
  2. import 'package:fis_common/event/event_type.dart';
  3. import 'package:fis_common/func/func_proxy.dart';
  4. import 'package:fis_measure/interfaces/process/player/play_controller.dart';
  5. import 'package:fis_ui/index.dart';
  6. import 'package:fis_vid/data_channel/channel.dart';
  7. import 'package:fis_vid/data_host/data_host.dart';
  8. import 'package:flutter/foundation.dart';
  9. import 'package:vid/us/vid_us_image.dart';
  10. import 'package:vid/us/vid_us_probe.dart';
  11. import 'enums.dart';
  12. import 'events.dart';
  13. /// Vid播放器控制器
  14. class VidPlayerControllerNoSharing extends ChangeNotifier
  15. implements IPlayerController {
  16. /// Vid播放器控制器
  17. ///
  18. /// [dataHost] Vid文件宿主
  19. VidPlayerControllerNoSharing({
  20. required VidDataHost dataHost,
  21. }) {
  22. _dataHost = dataHost;
  23. eventHandler = FEventHandler<VidPlayerEvent>();
  24. frameUpdated = FEventHandler<VidUsImage>();
  25. firstFrameLoaded = FEventHandler<VidUsImage>();
  26. frameLoadStateChanged = FEventHandler<bool>();
  27. errorOccured = FEventHandler<String?>();
  28. }
  29. // ignore: constant_identifier_names
  30. static const _CAN_PLAY_STATUS_ARR = [
  31. VidPlayStatus.ready,
  32. VidPlayStatus.pause
  33. ];
  34. // ignore: constant_identifier_names
  35. static const _HAS_VIEW_STATUS_ARR = [VidPlayStatus.play, VidPlayStatus.pause];
  36. @override
  37. var eventHandler = FEventHandler<VidPlayerEvent>();
  38. var currentFrameHandler = FEventHandler<VidUsImage>();
  39. @override
  40. late final FEventHandler<VidUsImage> frameUpdated;
  41. @override
  42. late final FEventHandler<VidUsImage> firstFrameLoaded;
  43. @override
  44. late final FEventHandler<bool> frameLoadStateChanged;
  45. @override
  46. late final FEventHandler<String?> errorOccured;
  47. late final VidDataHost _dataHost;
  48. _PlayAssistant? _playAssistant;
  49. double _speed = 1.0;
  50. VidPlayStatus _status = VidPlayStatus.init;
  51. int _frameIndex = -1;
  52. VidUsImage? _frame;
  53. bool _disposed = false;
  54. ///该图像是否需要获取测量项和注释项
  55. bool ifNeedInit = true;
  56. @override
  57. bool get disposed => _disposed;
  58. /// Current play speed
  59. double get currentSpeed => _speed;
  60. @override
  61. VidPlayStatus get status => _status;
  62. @override
  63. VidUsImage? get currentFrame => _frame;
  64. /// Whether the player is playing
  65. bool get playing => status == VidPlayStatus.play;
  66. /// Whether the player can play
  67. bool get canPlay => _CAN_PLAY_STATUS_ARR.contains(status);
  68. /// Whether the player should has view
  69. @override
  70. bool get hasView => _HAS_VIEW_STATUS_ARR.contains(status);
  71. /// Current viewed frame index
  72. int get currentFrameIndex => _frameIndex;
  73. /// Total frames count of current vid
  74. int get totalFramesCount => _dataHost.frameCount;
  75. double get frameRate => _dataHost.probe.frameRate;
  76. bool get isSingleFrame => totalFramesCount == 1;
  77. /// 是否播放结束
  78. bool get isEndOfPlay => currentFrameIndex == totalFramesCount - 1;
  79. /// 当前播放器亮度 初始值为 0
  80. double get brightness => _brightness;
  81. double _brightness = 0.0;
  82. /// 当前播放器对比度 初始值为 1
  83. double get contrast => _contrast;
  84. double _contrast = 1.0;
  85. /// Set play speed [0.5~2]
  86. ///
  87. /// [speed] speed value [0.5~2]
  88. void setSpeed(double speed) {
  89. if (speed < 0.5 || speed > 2) return;
  90. _speed = speed;
  91. eventHandler.emit(this, VidPlayerSpeedChangeEvent(currentSpeed));
  92. }
  93. @override
  94. Future<bool> load() async {
  95. ifNeedInit = true;
  96. final info = await _dataHost.load();
  97. final result = info != null;
  98. if (result) {
  99. _setStatus(VidPlayStatus.ready);
  100. } else {
  101. _setStatus(VidPlayStatus.loadFail);
  102. }
  103. return result;
  104. }
  105. @override
  106. void play() {
  107. if (playing) return;
  108. if (!canPlay) return;
  109. if (isEndOfPlay) {
  110. _frameIndex = -1;
  111. }
  112. if (isSingleFrame) {
  113. gotoFrame(0);
  114. _setStatus(VidPlayStatus.pause);
  115. } else {
  116. _playAssistant ??= _PlayAssistant(this);
  117. _playAssistant!.play();
  118. _setStatus(VidPlayStatus.play);
  119. }
  120. }
  121. @override
  122. void pause() {
  123. if (!playing) {
  124. if (_status != VidPlayStatus.pause) {
  125. _setStatus(VidPlayStatus.pause);
  126. }
  127. return;
  128. }
  129. _playAssistant?.pause();
  130. _setStatus(VidPlayStatus.pause);
  131. }
  132. /// 主动播放结束
  133. void playOver() {
  134. pause();
  135. eventHandler.emit(this, VidPlayerPlayOverEvent());
  136. }
  137. /// Pause and view next frame
  138. Future<bool> gotoNextFrame() {
  139. pause();
  140. return gotoFrame(currentFrameIndex + 1);
  141. }
  142. /// Pause and view prev frame
  143. Future<bool> gotoPrevFrame() {
  144. pause();
  145. return gotoFrame(currentFrameIndex - 1);
  146. }
  147. /// View target indexed frame
  148. ///
  149. /// [index] frame index
  150. Future<bool> gotoFrame(int index) async {
  151. if (index < 0 || index >= totalFramesCount) return false;
  152. if (index == currentFrameIndex) return true;
  153. _frameIndex = index;
  154. _updateFrame();
  155. return true;
  156. }
  157. /// Set frame brightness
  158. ///
  159. /// [value] brightness value
  160. void setBrightness(int value) {
  161. final brightnessCount = value / 100;
  162. if (brightnessCount < -1 || brightnessCount > 1) {
  163. return;
  164. }
  165. if (kIsMobile) {
  166. _brightness = brightnessCount * 255;
  167. } else {
  168. _brightness = brightnessCount;
  169. }
  170. final fliterMatrix = <double>[
  171. contrast, 0, 0, 0, brightness, // red
  172. 0, contrast, 0, 0, brightness, // green
  173. 0, 0, contrast, 0, brightness, // blue
  174. 0, 0, 0, 1, 0, // alpha // alpha
  175. ];
  176. eventHandler.emit(this, VidPlayerFilterChangeEvent(fliterMatrix));
  177. _updateFrame();
  178. }
  179. /// Set frame contrast
  180. ///
  181. /// [value] contrast value
  182. void setContrast(int value) {
  183. double contrastCount = 1;
  184. if (value < 0) {
  185. contrastCount = (value + 100) / 100;
  186. } else if (value >= 0) {
  187. contrastCount = value / 100 * 9 + 1;
  188. }
  189. if (contrastCount < 0 || contrastCount > 10) {
  190. return;
  191. }
  192. _contrast = contrastCount;
  193. final fliterMatrix = <double>[
  194. contrast, 0, 0, 0, brightness, // red
  195. 0, contrast, 0, 0, brightness, // green
  196. 0, 0, contrast, 0, brightness, // blue
  197. 0, 0, 0, 1, 0, // alpha
  198. ];
  199. eventHandler.emit(this, VidPlayerFilterChangeEvent(fliterMatrix));
  200. _updateFrame();
  201. }
  202. void setFilterMatrix(List<double> matrix) {
  203. eventHandler.emit(this, VidPlayerFilterChangeEvent(matrix));
  204. }
  205. /// 重置图像增益
  206. void resetTone() {
  207. setBrightness(0);
  208. setContrast(0);
  209. eventHandler.emit(this, VidPlayResetToneEvent());
  210. }
  211. void _updateFrame() {
  212. _handleUpdateFrame
  213. .throttle(
  214. timeout: _playAssistant?._playIntervalMillSeconds ?? 200,
  215. )
  216. .call();
  217. }
  218. /// [Carotid] ✅用于设置颈动脉单帧展示
  219. void set2DMeasureFrame(VidUsImage _frame) {
  220. eventHandler.emit(
  221. this,
  222. VidPlayerFrameIndexChangeEvent(
  223. currentFrameIndex,
  224. _frame.imageData,
  225. _frame.width,
  226. _frame.height,
  227. ),
  228. );
  229. }
  230. /// [Carotid] ✅用于重置播放器
  231. void resetCurrentFrame() {
  232. _frameIndex = -1;
  233. play();
  234. }
  235. Future<void> _handleUpdateFrame() async {
  236. if (_disposed) return;
  237. _frame = await _dataHost.getFrame(currentFrameIndex);
  238. emitFrameUpdate();
  239. }
  240. void emitFrameUpdate() {
  241. if (ifNeedInit) {
  242. currentFrameHandler.emit(this, _frame!);
  243. ifNeedInit = false;
  244. }
  245. eventHandler.emit(
  246. this,
  247. VidPlayerFrameIndexChangeEvent(
  248. currentFrameIndex,
  249. _frame!.imageData,
  250. _frame!.width,
  251. _frame!.height,
  252. ),
  253. );
  254. }
  255. void _setStatus(VidPlayStatus value) {
  256. _status = value;
  257. _notifyStatus();
  258. }
  259. void _notifyStatus() {
  260. eventHandler.emit(this, VidPlayerStatusChangeEvent(status));
  261. }
  262. void _stop({bool needNotify = true}) {
  263. _playAssistant?.pause();
  264. if (needNotify) {
  265. _setStatus(VidPlayStatus.stop);
  266. }
  267. }
  268. @override
  269. void dispose() {
  270. _dataHost.release();
  271. _disposed = true;
  272. _stop(needNotify: false);
  273. eventHandler.dispose();
  274. super.dispose();
  275. }
  276. /// 已禁用,请通过eventHandler监听事件
  277. @override
  278. void addListener(VoidCallback listener) {
  279. throw UnsupportedError(
  280. "method `addListener` has been limited.Pls use `eventHandler.addListener`.");
  281. }
  282. /// 已禁用,请通过eventHandler监听事件
  283. @override
  284. void removeListener(VoidCallback listener) {
  285. throw UnsupportedError(
  286. "method `removeListener` has been limited.Pls use `eventHandler.removeListener`.");
  287. }
  288. @override
  289. VidDataChannel get dataChannel => throw UnimplementedError();
  290. @override
  291. Future<bool> locateTo(int index) {
  292. pause();
  293. return gotoFrame(index);
  294. }
  295. @override
  296. String get url => _dataHost.url;
  297. VidUsProbe get probe => _dataHost.probe;
  298. }
  299. class _PlayAssistant {
  300. _PlayAssistant(this.owner);
  301. final VidPlayerControllerNoSharing owner;
  302. bool _ready = false;
  303. late double _frameRate;
  304. int get _playInterval => 1000 * 1000 ~/ _frameRate;
  305. int get _playIntervalMillSeconds => _playInterval ~/ 1000.0;
  306. Timer? _timer;
  307. void play() {
  308. if (!_ready) {
  309. _prepare();
  310. }
  311. if (_timer != null) {
  312. pause();
  313. }
  314. final duration = Duration(microseconds: _playInterval);
  315. // final duration = const Duration(milliseconds: 1000 ~/ 10);
  316. _timer = Timer.periodic(duration, (timer) {
  317. // print('play at ${DateTime.now()}');
  318. owner.gotoFrame(owner.currentFrameIndex + 1);
  319. if (owner.currentFrameIndex == owner.totalFramesCount - 1) {
  320. owner.playOver();
  321. }
  322. });
  323. }
  324. void pause() {
  325. _timer?.cancel();
  326. _timer = null;
  327. print('stop at ${DateTime.now()}');
  328. }
  329. void _prepare() {
  330. _frameRate = owner._dataHost.probe.frameRate;
  331. _ready = true;
  332. }
  333. }