controller_old.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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. double get frameRate => _dataHost.probe.frameRate;
  75. bool get isSingleFrame => totalFramesCount == 1;
  76. /// 是否播放结束
  77. bool get isEndOfPlay => currentFrameIndex == totalFramesCount - 1;
  78. /// 当前播放器亮度 初始值为 0
  79. double get brightness => _brightness;
  80. double _brightness = 0.0;
  81. /// 当前播放器对比度 初始值为 1
  82. double get contrast => _contrast;
  83. double _contrast = 1.0;
  84. /// Set play speed [0.5~2]
  85. ///
  86. /// [speed] speed value [0.5~2]
  87. void setSpeed(double speed) {
  88. if (speed < 0.5 || speed > 2) return;
  89. _speed = speed;
  90. eventHandler.emit(this, VidPlayerSpeedChangeEvent(currentSpeed));
  91. }
  92. @override
  93. Future<bool> load() async {
  94. ifNeedInit = true;
  95. final info = await _dataHost.load();
  96. final result = info != null;
  97. if (result) {
  98. _setStatus(VidPlayStatus.ready);
  99. } else {
  100. _setStatus(VidPlayStatus.loadFail);
  101. }
  102. return result;
  103. }
  104. @override
  105. void play() {
  106. if (playing) return;
  107. if (!canPlay) return;
  108. if (isEndOfPlay) {
  109. _frameIndex = -1;
  110. }
  111. if (isSingleFrame) {
  112. gotoFrame(0);
  113. _setStatus(VidPlayStatus.pause);
  114. } else {
  115. _playAssistant ??= _PlayAssistant(this);
  116. _playAssistant!.play();
  117. _setStatus(VidPlayStatus.play);
  118. }
  119. }
  120. @override
  121. void pause() {
  122. if (!playing) {
  123. if (_status != VidPlayStatus.pause) {
  124. _setStatus(VidPlayStatus.pause);
  125. }
  126. return;
  127. }
  128. _playAssistant?.pause();
  129. _setStatus(VidPlayStatus.pause);
  130. }
  131. /// 主动播放结束
  132. void playOver() {
  133. pause();
  134. eventHandler.emit(this, VidPlayerPlayOverEvent());
  135. }
  136. /// Pause and view next frame
  137. Future<bool> gotoNextFrame() {
  138. pause();
  139. return gotoFrame(currentFrameIndex + 1);
  140. }
  141. /// Pause and view prev frame
  142. Future<bool> gotoPrevFrame() {
  143. pause();
  144. return gotoFrame(currentFrameIndex - 1);
  145. }
  146. /// View target indexed frame
  147. ///
  148. /// [index] frame index
  149. Future<bool> gotoFrame(int index) async {
  150. if (index < 0 || index >= totalFramesCount) return false;
  151. _frameIndex = index;
  152. _updateFrame();
  153. return true;
  154. }
  155. /// Set frame brightness
  156. ///
  157. /// [value] brightness value
  158. void setBrightness(int value) {
  159. final brightnessCount = value / 100;
  160. if (brightnessCount < -1 || brightnessCount > 1) {
  161. return;
  162. }
  163. if (kIsMobile) {
  164. _brightness = brightnessCount * 255;
  165. } else {
  166. _brightness = brightnessCount;
  167. }
  168. final fliterMatrix = <double>[
  169. contrast, 0, 0, 0, brightness, // red
  170. 0, contrast, 0, 0, brightness, // green
  171. 0, 0, contrast, 0, brightness, // blue
  172. 0, 0, 0, 1, 0, // alpha // alpha
  173. ];
  174. eventHandler.emit(this, VidPlayerFilterChangeEvent(fliterMatrix));
  175. _updateFrame();
  176. }
  177. /// Set frame contrast
  178. ///
  179. /// [value] contrast value
  180. void setContrast(int value) {
  181. double contrastCount = 1;
  182. if (value < 0) {
  183. contrastCount = (value + 100) / 100;
  184. } else if (value >= 0) {
  185. contrastCount = value / 100 * 9 + 1;
  186. }
  187. if (contrastCount < 0 || contrastCount > 10) {
  188. return;
  189. }
  190. _contrast = contrastCount;
  191. final fliterMatrix = <double>[
  192. contrast, 0, 0, 0, brightness, // red
  193. 0, contrast, 0, 0, brightness, // green
  194. 0, 0, contrast, 0, brightness, // blue
  195. 0, 0, 0, 1, 0, // alpha
  196. ];
  197. eventHandler.emit(this, VidPlayerFilterChangeEvent(fliterMatrix));
  198. _updateFrame();
  199. }
  200. void setFilterMatrix(List<double> matrix) {
  201. eventHandler.emit(this, VidPlayerFilterChangeEvent(matrix));
  202. }
  203. /// 重置图像增益
  204. void resetTone() {
  205. setBrightness(0);
  206. setContrast(0);
  207. eventHandler.emit(this, VidPlayResetToneEvent());
  208. }
  209. void _updateFrame() {
  210. _handleUpdateFrame
  211. .throttle(
  212. timeout: _playAssistant?._playIntervalMillSeconds ?? 200,
  213. )
  214. .call();
  215. }
  216. /// [Carotid] ✅用于设置颈动脉单帧展示
  217. void set2DMeasureFrame(VidUsImage _frame) {
  218. eventHandler.emit(
  219. this,
  220. VidPlayerFrameIndexChangeEvent(
  221. currentFrameIndex,
  222. _frame.imageData,
  223. _frame.width,
  224. _frame.height,
  225. ),
  226. );
  227. }
  228. /// [Carotid] ✅用于重置播放器
  229. void resetCurrentFrame() {
  230. _frameIndex = -1;
  231. play();
  232. }
  233. Future<void> _handleUpdateFrame() async {
  234. if (_disposed) return;
  235. _frame = await _dataHost.getFrame(currentFrameIndex);
  236. emitFrameUpdate();
  237. }
  238. void emitFrameUpdate() {
  239. if (ifNeedInit) {
  240. currentFrameHandler.emit(this, _frame!);
  241. ifNeedInit = false;
  242. }
  243. eventHandler.emit(
  244. this,
  245. VidPlayerFrameIndexChangeEvent(
  246. currentFrameIndex,
  247. _frame!.imageData,
  248. _frame!.width,
  249. _frame!.height,
  250. ),
  251. );
  252. }
  253. void _setStatus(VidPlayStatus value) {
  254. _status = value;
  255. _notifyStatus();
  256. }
  257. void _notifyStatus() {
  258. eventHandler.emit(this, VidPlayerStatusChangeEvent(status));
  259. }
  260. void _stop({bool needNotify = true}) {
  261. _playAssistant?.pause();
  262. if (needNotify) {
  263. _setStatus(VidPlayStatus.stop);
  264. }
  265. }
  266. @override
  267. void dispose() {
  268. _dataHost.release();
  269. _disposed = true;
  270. _stop(needNotify: false);
  271. eventHandler.dispose();
  272. super.dispose();
  273. }
  274. /// 已禁用,请通过eventHandler监听事件
  275. @override
  276. void addListener(VoidCallback listener) {
  277. throw UnsupportedError(
  278. "method `addListener` has been limited.Pls use `eventHandler.addListener`.");
  279. }
  280. /// 已禁用,请通过eventHandler监听事件
  281. @override
  282. void removeListener(VoidCallback listener) {
  283. throw UnsupportedError(
  284. "method `removeListener` has been limited.Pls use `eventHandler.removeListener`.");
  285. }
  286. @override
  287. VidDataChannel get dataChannel => throw UnimplementedError();
  288. @override
  289. Future<bool> locateTo(int index) {
  290. pause();
  291. return gotoFrame(index);
  292. }
  293. @override
  294. String get url => _dataHost.url;
  295. }
  296. class _PlayAssistant {
  297. _PlayAssistant(this.owner);
  298. final VidPlayerControllerNoSharing owner;
  299. bool _ready = false;
  300. late double _frameRate;
  301. int get _playInterval => 1000 * 1000 ~/ _frameRate;
  302. int get _playIntervalMillSeconds => _playInterval ~/ 1000.0;
  303. Timer? _timer;
  304. void play() {
  305. if (!_ready) {
  306. _prepare();
  307. }
  308. if (_timer != null) {
  309. pause();
  310. }
  311. final duration = Duration(microseconds: _playInterval);
  312. // final duration = const Duration(milliseconds: 1000 ~/ 10);
  313. _timer = Timer.periodic(duration, (timer) {
  314. // print('play at ${DateTime.now()}');
  315. owner.gotoFrame(owner.currentFrameIndex + 1);
  316. if (owner.currentFrameIndex == owner.totalFramesCount - 1) {
  317. owner.playOver();
  318. }
  319. });
  320. }
  321. void pause() {
  322. _timer?.cancel();
  323. _timer = null;
  324. print('stop at ${DateTime.now()}');
  325. }
  326. void _prepare() {
  327. _frameRate = owner._dataHost.probe.frameRate;
  328. _ready = true;
  329. }
  330. }