vid_data.dart 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import 'dart:convert';
  2. import 'dart:typed_data';
  3. import 'package:fis_common/env/env.dart';
  4. import 'package:fis_common/web/shell_api_hepler.dart';
  5. import 'package:flutter/foundation.dart';
  6. import 'package:vid/us/vid_us_data_http_reader.dart';
  7. import 'package:vid/us/vid_us_data_reader.dart';
  8. import 'package:vid/us/vid_us_image.dart';
  9. import 'package:vid/us/vid_us_image_data.dart';
  10. import 'package:vid/us/vid_us_probe.dart';
  11. import 'reader.dart';
  12. import 'shell/reader.dart';
  13. abstract class AsyncVidImageDataBase {
  14. late AsyncVidDataReaderBase _reader;
  15. late List<int> _imagePositionList;
  16. late int _version;
  17. late int _imageCount;
  18. late VidUsProbe _probe;
  19. late VidUsImageFormat _imageFormat;
  20. late Uint8List _extendedData;
  21. late int _readHeaderTimeout;
  22. late int _readImageTimeout;
  23. late bool _initialized;
  24. late bool _closed;
  25. final Duration delayDuration = const Duration(milliseconds: 10);
  26. static final String vid_header = "VINNO IMAGE DATA";
  27. /// Gets the version of this image data.
  28. int get version => _version;
  29. /// Gets the image count of this image data.
  30. int get imageCount => _imageCount;
  31. /// Gets the probe information.
  32. VidUsProbe get probe => _probe;
  33. /// Gets the image format of this image data.
  34. VidUsImageFormat get imageFormat => _imageFormat;
  35. /// Gets the extended data.
  36. Uint8List get extendedData => _extendedData;
  37. /// Gets the initialized state.
  38. bool get initialized => _initialized;
  39. /// Create a VINNO Image Data.
  40. /// [readHeaderTimeout] is the timeout value of reading header and probe information etc..., we need give as much time as possible
  41. /// to let the reader read the header.
  42. /// [readImageTimeout] is the timeout value of reading one frame.
  43. /// [minChunkSize] The min download chunk size, set to a large value may speedup the download speed, but will cause the progress not smooth.
  44. AsyncVidImageDataBase(
  45. String url, {
  46. DownloadCallback? downloadCallback,
  47. int readHeaderTimeout = 3000,
  48. int readImageTimeout = 500,
  49. }) {
  50. _initialized = false;
  51. _closed = false;
  52. _readHeaderTimeout = readHeaderTimeout;
  53. _readImageTimeout = readImageTimeout;
  54. _reader = createReader(url, downloadCallback: downloadCallback);
  55. }
  56. @protected
  57. AsyncVidDataReaderBase createReader(String url,
  58. {DownloadCallback? downloadCallback});
  59. ///Get the downloaded data of this HttpVidUsImageData
  60. Uint8List getDownloadedData() {
  61. return _reader.toBytes();
  62. }
  63. void setReadHeaderTimeout(int timeout) => _readHeaderTimeout = timeout;
  64. void setReadImageTimeout(int timeout) => _readImageTimeout = timeout;
  65. ///Initialize the HttpVidUsImageData, must be called firstly.
  66. Future<bool> initialize() async {
  67. if (!_initialized) {
  68. String header;
  69. if (_reader.isVrd) {
  70. header = vid_header;
  71. } else {
  72. header = await _readHeader();
  73. }
  74. if (header != vid_header) {
  75. throw Exception("The input data is not a VID data.");
  76. }
  77. if (_reader.isVrd) {
  78. _version = await _getVersion();
  79. _probe = await _getProbe();
  80. _imageFormat = await _getImageFormat();
  81. _extendedData = await _getExtendedData();
  82. _imageCount = await _getImageCount();
  83. print('_imageCount:$_imageCount');
  84. } else {
  85. _version = await _readVersion();
  86. //Get probe info
  87. _probe = await _readProbe();
  88. _imageFormat = await _readImageFormat();
  89. _extendedData = await _readExtendedData();
  90. _imagePositionList = [];
  91. var imagePositionListData = await _readImagePositionListData();
  92. _imageCount = imagePositionListData.length ~/ 8;
  93. var imagePositionReader = VidUsDataReader(imagePositionListData);
  94. for (var i = 0; i < _imageCount; i++) {
  95. _imagePositionList.add(imagePositionReader.readInt64V2());
  96. }
  97. }
  98. _initialized = true;
  99. }
  100. return _initialized;
  101. }
  102. ///Close the HttpVidUsImageData, it will force close the download operation and reading operation.
  103. void close() {
  104. if (_closed) return;
  105. _closed = true;
  106. _reader.close();
  107. }
  108. T getReader<T extends AsyncVidDataReaderBase>() => _reader as T;
  109. ///Read header from http data.
  110. Future<String> _readHeader() async {
  111. var timeout = 0;
  112. while (!_closed) {
  113. try {
  114. var header = _reader.readString();
  115. return header;
  116. } catch (ex) {
  117. if (ex is NotReadyException) {
  118. if (timeout >= _readHeaderTimeout) {
  119. throw ReadTimeoutException();
  120. }
  121. await Future.delayed(delayDuration);
  122. timeout += delayDuration.inMilliseconds;
  123. } else {
  124. rethrow;
  125. }
  126. }
  127. }
  128. throw AlreadyClosedException();
  129. }
  130. ///Read the version from http data.
  131. Future<int> _readVersion() async {
  132. var timeout = 0;
  133. while (!_closed) {
  134. try {
  135. var version = _reader.readInt();
  136. return version;
  137. } catch (ex) {
  138. if (ex is NotReadyException) {
  139. if (timeout >= _readHeaderTimeout) {
  140. throw ReadTimeoutException();
  141. }
  142. await Future.delayed(delayDuration);
  143. timeout += delayDuration.inMilliseconds;
  144. } else {
  145. rethrow;
  146. }
  147. }
  148. }
  149. throw AlreadyClosedException();
  150. }
  151. ///Read the probe info from http data.
  152. Future<VidUsProbe> _readProbe() async {
  153. var timeout = 0;
  154. while (!_closed) {
  155. try {
  156. var probeData = _reader.readBytes();
  157. return VidUsProbe.fromBytes(probeData);
  158. } catch (ex) {
  159. if (ex is NotReadyException) {
  160. if (timeout >= _readHeaderTimeout) {
  161. throw ReadTimeoutException();
  162. }
  163. await Future.delayed(delayDuration);
  164. timeout += delayDuration.inMilliseconds;
  165. } else {
  166. rethrow;
  167. }
  168. }
  169. }
  170. throw AlreadyClosedException();
  171. }
  172. ///Read the image format from http data.
  173. Future<VidUsImageFormat> _readImageFormat() async {
  174. var timeout = 0;
  175. while (!_closed) {
  176. try {
  177. return VidUsImageFormat.values[_reader.readInt()];
  178. } catch (ex) {
  179. if (ex is NotReadyException) {
  180. if (timeout >= _readHeaderTimeout) {
  181. throw ReadTimeoutException();
  182. }
  183. await Future.delayed(delayDuration);
  184. timeout += delayDuration.inMilliseconds;
  185. } else {
  186. rethrow;
  187. }
  188. }
  189. }
  190. throw AlreadyClosedException();
  191. }
  192. ///Read extended data from http data.
  193. Future<Uint8List> _readExtendedData() async {
  194. var timeout = 0;
  195. while (!_closed) {
  196. try {
  197. return _reader.readBytes();
  198. } catch (ex) {
  199. if (ex is NotReadyException) {
  200. if (timeout >= _readHeaderTimeout) {
  201. throw ReadTimeoutException();
  202. }
  203. await Future.delayed(delayDuration);
  204. timeout += delayDuration.inMilliseconds;
  205. } else {
  206. rethrow;
  207. }
  208. }
  209. }
  210. throw AlreadyClosedException();
  211. }
  212. ///Read the image positions data from http data.
  213. Future<Uint8List> _readImagePositionListData() async {
  214. var timeout = 0;
  215. while (!_closed) {
  216. try {
  217. return _reader.readBytes();
  218. } catch (ex) {
  219. if (ex is NotReadyException) {
  220. if (timeout >= _readHeaderTimeout) {
  221. throw ReadTimeoutException();
  222. }
  223. await Future.delayed(delayDuration);
  224. timeout += delayDuration.inMilliseconds;
  225. } else {
  226. rethrow;
  227. }
  228. }
  229. }
  230. throw AlreadyClosedException();
  231. }
  232. /// Get one image from the vid.
  233. Future<VidUsImage> getImage(int index) async {
  234. if (index >= _imageCount || index < 0) {
  235. throw Exception("Can not find image Data");
  236. }
  237. //Jump to image.
  238. var timeout = 0;
  239. while (!_closed) {
  240. try {
  241. print('_reader.readBytes $index');
  242. Uint8List imageData;
  243. if (_reader.isVrd) {
  244. imageData = _reader.getImageBytes(index);
  245. if (imageData.isEmpty) {
  246. _reader.skipToFrame(index);
  247. throw Exception("Can not find image Data");
  248. }
  249. } else {
  250. imageData = _reader.readBytes(_imagePositionList[index]);
  251. }
  252. print('_reader.readBytes $index done');
  253. return VidUsImage.fromBytes(imageData);
  254. } catch (ex) {
  255. print('_reader.readBytes $index ex:$ex');
  256. if (ex is NotReadyException) {
  257. if (timeout >= _readImageTimeout) {
  258. throw ReadTimeoutException();
  259. }
  260. await Future.delayed(delayDuration);
  261. timeout += delayDuration.inMilliseconds;
  262. } else {
  263. rethrow;
  264. }
  265. }
  266. }
  267. throw AlreadyClosedException();
  268. }
  269. Future<int> _getVersion() async {
  270. final result = await ShellApiHelper.call(
  271. 'getVersion',
  272. {
  273. 'Url': _reader.url,
  274. },
  275. );
  276. print('_getVersion:$result');
  277. return result;
  278. }
  279. Future<VidUsProbe> _getProbe() async {
  280. final result = await ShellApiHelper.call(
  281. 'getVinnoProbe',
  282. {
  283. 'Url': _reader.url,
  284. },
  285. );
  286. var probe = base64Decode(result);
  287. var probeResult = VidUsProbe.fromBytes(probe);
  288. print("probe : ${probeResult.name} ${probeResult.type}");
  289. return probeResult;
  290. }
  291. Future<VidUsImageFormat> _getImageFormat() async {
  292. final result = await ShellApiHelper.call(
  293. 'getImageFormat',
  294. {
  295. 'Url': _reader.url,
  296. },
  297. );
  298. return VidUsImageFormat.values
  299. .firstWhere((element) => element.index == result);
  300. }
  301. Future<Uint8List> _getExtendedData() async {
  302. final result = await ShellApiHelper.call(
  303. 'getExtendedData',
  304. {
  305. 'Url': _reader.url,
  306. },
  307. );
  308. return base64Decode(result);
  309. }
  310. Future<int> _getImageCount() async {
  311. final result = await ShellApiHelper.call(
  312. 'getImageCount',
  313. {
  314. 'Url': _reader.url,
  315. },
  316. );
  317. return result;
  318. }
  319. }