vid_data.dart 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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(
  236. "Can not find image Data: index ($index) out of range ([0:${_imageCount - 1}])");
  237. }
  238. //Jump to image.
  239. var timeout = 0;
  240. while (!_closed) {
  241. try {
  242. print('_reader.readBytes index:$index start');
  243. Uint8List imageData;
  244. if (_reader.isVrd) {
  245. imageData = _reader.getImageBytes(index);
  246. if (imageData.isEmpty) {
  247. // _reader.skipToFrame(index);
  248. throw NotReadyException();
  249. }
  250. } else {
  251. imageData = _reader.readBytes(_imagePositionList[index]);
  252. }
  253. print('_reader.readBytes index:$index done');
  254. return VidUsImage.fromBytes(imageData);
  255. } catch (ex) {
  256. print('_reader.readBytes index:$index error ex:$ex');
  257. if (ex is NotReadyException) {
  258. if (timeout >= _readImageTimeout) {
  259. throw ReadTimeoutException();
  260. }
  261. await Future.delayed(delayDuration);
  262. timeout += delayDuration.inMilliseconds;
  263. } else {
  264. rethrow;
  265. }
  266. }
  267. }
  268. throw AlreadyClosedException();
  269. }
  270. Future<int> _getVersion() async {
  271. final result = await ShellApiHelper.call(
  272. 'getVersion',
  273. {
  274. 'Url': _reader.url,
  275. },
  276. );
  277. print('_getVersion:$result');
  278. return result;
  279. }
  280. Future<VidUsProbe> _getProbe() async {
  281. final result = await ShellApiHelper.call(
  282. 'getVinnoProbe',
  283. {
  284. 'Url': _reader.url,
  285. },
  286. );
  287. var probe = base64Decode(result);
  288. var probeResult = VidUsProbe.fromBytes(probe);
  289. print("probe : ${probeResult.name} ${probeResult.type}");
  290. return probeResult;
  291. }
  292. Future<VidUsImageFormat> _getImageFormat() async {
  293. final result = await ShellApiHelper.call(
  294. 'getImageFormat',
  295. {
  296. 'Url': _reader.url,
  297. },
  298. );
  299. return VidUsImageFormat.values
  300. .firstWhere((element) => element.index == result);
  301. }
  302. Future<Uint8List> _getExtendedData() async {
  303. final result = await ShellApiHelper.call(
  304. 'getExtendedData',
  305. {
  306. 'Url': _reader.url,
  307. },
  308. );
  309. return base64Decode(result);
  310. }
  311. Future<int> _getImageCount() async {
  312. final result = await ShellApiHelper.call(
  313. 'getImageCount',
  314. {
  315. 'Url': _reader.url,
  316. },
  317. );
  318. return result;
  319. }
  320. }