controller_old.dart 9.1 KB

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