controller_old.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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. _disposed = true;
  258. _stop(needNotify: false);
  259. eventHandler.dispose();
  260. super.dispose();
  261. }
  262. /// 已禁用,请通过eventHandler监听事件
  263. @override
  264. void addListener(VoidCallback listener) {
  265. throw UnsupportedError(
  266. "method `addListener` has been limited.Pls use `eventHandler.addListener`.");
  267. }
  268. /// 已禁用,请通过eventHandler监听事件
  269. @override
  270. void removeListener(VoidCallback listener) {
  271. throw UnsupportedError(
  272. "method `removeListener` has been limited.Pls use `eventHandler.removeListener`.");
  273. }
  274. @override
  275. VidDataChannel get dataChannel => throw UnimplementedError();
  276. @override
  277. Future<bool> locateTo(int index) {
  278. pause();
  279. return gotoFrame(index);
  280. }
  281. @override
  282. String get url => _dataHost.url;
  283. }
  284. class _PlayAssistant {
  285. _PlayAssistant(this.owner);
  286. final VidPlayerControllerNoSharing owner;
  287. bool _ready = false;
  288. late double _frameRate;
  289. int get _playInterval => 1000 * 1000 ~/ _frameRate;
  290. int get _playIntervalMillSeconds => _playInterval ~/ 1000.0;
  291. Timer? _timer;
  292. void play() {
  293. if (!_ready) {
  294. _prepare();
  295. }
  296. if (_timer != null) {
  297. pause();
  298. }
  299. final duration = Duration(microseconds: _playInterval);
  300. // final duration = const Duration(milliseconds: 1000 ~/ 10);
  301. _timer = Timer.periodic(duration, (timer) {
  302. // print('play at ${DateTime.now()}');
  303. owner.gotoFrame(owner.currentFrameIndex + 1);
  304. if (owner.currentFrameIndex == owner.totalFramesCount - 1) {
  305. owner.pause();
  306. }
  307. });
  308. }
  309. void pause() {
  310. _timer?.cancel();
  311. _timer = null;
  312. print('stop at ${DateTime.now()}');
  313. }
  314. void _prepare() {
  315. _frameRate = owner._dataHost.probe.frameRate;
  316. _ready = true;
  317. }
  318. }