Justin 2 years ago
parent
commit
44d3d2466d
2 changed files with 122 additions and 95 deletions
  1. 84 77
      lib/us/vid_us_data_http_reader.dart
  2. 38 18
      lib/us/vid_us_image_data.dart

+ 84 - 77
lib/us/vid_us_data_http_reader.dart

@@ -1,29 +1,24 @@
 import 'dart:typed_data';
-
 import 'package:dio/dio.dart';
-import 'package:flutter/foundation.dart';
 
 //Raised when data is not ready.
 class NotReadyException implements Exception {}
 
 //Raised when errro happened during the downloading.
 class DownloadErrorException implements Exception {
-  String _msg;
+  String _message;
 
-  DownloadErrorException(this._msg);
+  String get message => _message;
 
-  @override
-  String toString() {
-    return _msg;
-  }
+  DownloadErrorException(this._message);
 }
 
 typedef DownloadCallback = void Function(double progress);
 
 class VidUsDataHttpReader {
-  late final List<int> _data = [];
+  late Uint8List _underlyingData = Uint8List(0);
+  late int _bufferSize = 0;
   late int _index;
-  late ByteBuffer _buffer;
   late bool _error;
   late String _errorMsg;
   late String _url;
@@ -32,47 +27,59 @@ class VidUsDataHttpReader {
 
   DownloadCallback? downloadCallback;
 
-  VidUsDataHttpReader(String url, {this.downloadCallback, int chunkSize = 32768}) {
+  VidUsDataHttpReader(String url, {this.downloadCallback, int chunkSize = 65536, int connectTimeout = 30000, int receiveTimeout = 30000}) {
     _chunkSize = chunkSize;
     _url = url;
     _error = false;
     _errorMsg = '';
-    _buffer = Uint8List.fromList(_data).buffer;
     _index = 0;
     _dio = Dio();
-    //TODO let the user set the timeout.
-    _dio.options.connectTimeout = 5000; //5S
-    _dio.options.receiveTimeout = 3000;
+    _dio.options.connectTimeout = connectTimeout;
+    _dio.options.receiveTimeout = receiveTimeout;
     _startDownload();
   }
 
   void _startDownload() async {
-    //get file info
-    var fileSize = await _getFileSize();
-    if (!_error) {
-      var last = fileSize % _chunkSize;
-      var chunkCount = fileSize ~/ _chunkSize;
-      for (var i = 0; i < chunkCount; i++) {
-        var start = i * _chunkSize;
-        var end = start + _chunkSize;
-        await _downloadChunk(start, end);
-        if (_error) {
-          break;
-        }
-        if (downloadCallback != null) {
-          var progress = _data.length / fileSize;
-          downloadCallback!(progress);
-        }
-      }
-      if (!_error && last > 0) {
-        var start = chunkCount * _chunkSize;
-        var end = start + last;
-        await _downloadChunk(start, end);
-        if (!_error && downloadCallback != null) {
-          var progress = _data.length / fileSize;
-          downloadCallback!(progress);
+    try {
+      //get file info
+      var fileSize = await _getFileSize();
+      if (!_error) {
+        _underlyingData = Uint8List(fileSize);
+        if (fileSize < _chunkSize) {
+          await _downloadChunk(0, fileSize -1);
+          if (!_error && downloadCallback != null) {
+            var progress = _bufferSize / fileSize;
+            downloadCallback!(progress);
+          }
+        } else {
+          var last = fileSize % _chunkSize;
+          var chunkCount = fileSize ~/ _chunkSize;
+          for (var i = 0; i < chunkCount; i++) {
+            var start = i * _chunkSize;
+            var end = start + _chunkSize - 1;
+            await _downloadChunk(start, end);
+            if (_error) {
+              break;
+            }
+            if (downloadCallback != null) {
+              var progress = _bufferSize / fileSize;
+              downloadCallback!(progress);
+            }
+          }
+          if (!_error && last > 0) {
+            var start = chunkCount * _chunkSize;
+            var end = start + last - 1;
+            await _downloadChunk(start, end);
+            if (!_error && downloadCallback != null) {
+              var progress = _bufferSize / fileSize;
+              downloadCallback!(progress);
+            }
+          }
         }
       }
+    } catch (ex) {
+      _error = true;
+      _errorMsg = ex.toString();
     }
   }
 
@@ -104,8 +111,8 @@ class VidUsDataHttpReader {
         _errorMsg = 'Download chunk error.';
       } else {
         //Update the buffer.
-        _data.addAll(downloadedData);
-        _buffer = Uint8List.fromList(_data).buffer;
+        _underlyingData.setAll(_bufferSize, downloadedData);
+        _bufferSize += downloadedData.length;
       }
     } else {
       _error = true;
@@ -114,7 +121,7 @@ class VidUsDataHttpReader {
   }
 
   //Close the reader and its http connection.
-  void close(){
+  void close() {
     _dio.close(force: true);
   }
 
@@ -124,17 +131,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 4) {
+      if ((_bufferSize - _index) < 4) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(_index, 4);
+      var intData = _underlyingData.buffer.asByteData(_index, 4);
       _index += 4;
       return intData.getInt32(0, Endian.little);
     } else {
-      if ((_buffer.lengthInBytes - index) < 4) {
+      if ((_bufferSize - index) < 4) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(index, 4);
+      var intData = _underlyingData.buffer.asByteData(index, 4);
       _index = index + 4;
       return intData.getInt32(0, Endian.little);
     }
@@ -148,16 +155,16 @@ class VidUsDataHttpReader {
     int dataLength;
     if (index == -1) {
       dataLength = readInt();
-      if ((_buffer.lengthInBytes - _index) < dataLength) {
+      if ((_bufferSize - _index) < dataLength) {
         throw NotReadyException();
       }
     } else {
       dataLength = readInt(index);
-      if ((_buffer.lengthInBytes - index) < dataLength) {
+      if ((_bufferSize - index) < dataLength) {
         throw NotReadyException();
       }
     }
-    var stringData = _buffer.asUint8List(_index, dataLength);
+    var stringData = _underlyingData.buffer.asUint8List(_index, dataLength);
     _index += dataLength;
     var unicodeStringData = Uint8List.fromList(stringData.toList()).buffer.asUint16List();
     return String.fromCharCodes(unicodeStringData);
@@ -169,17 +176,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 2) {
+      if ((_bufferSize - _index) < 2) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(_index, 2);
+      var intData = _underlyingData.buffer.asByteData(_index, 2);
       _index += 2;
       return intData.getInt16(0, Endian.little);
     } else {
-      if ((_buffer.lengthInBytes - index) < 2) {
+      if ((_bufferSize - index) < 2) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(index, 2);
+      var intData = _underlyingData.buffer.asByteData(index, 2);
       _index = index + 2;
       return intData.getInt16(0, Endian.little);
     }
@@ -192,17 +199,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 8) {
+      if ((_bufferSize - _index) < 8) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(_index, 8);
+      var intData = _underlyingData.buffer.asByteData(_index, 8);
       _index += 8;
       return intData.getInt64(0, Endian.little);
     } else {
-      if ((_buffer.lengthInBytes - index) < 8) {
+      if ((_bufferSize - index) < 8) {
         throw NotReadyException();
       }
-      var intData = _buffer.asByteData(index, 8);
+      var intData = _underlyingData.buffer.asByteData(index, 8);
       _index = index + 8;
       return intData.getInt64(0, Endian.little);
     }
@@ -215,7 +222,7 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 8) {
+      if ((_bufferSize - _index) < 8) {
         throw NotReadyException();
       }
       int low = readInt();
@@ -224,7 +231,7 @@ class VidUsDataHttpReader {
       value |= low;
       return value;
     } else {
-      if ((_buffer.lengthInBytes - index) < 8) {
+      if ((_bufferSize - index) < 8) {
         throw NotReadyException();
       }
       int low = readInt(index);
@@ -242,17 +249,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 4) {
+      if ((_bufferSize - _index) < 4) {
         throw NotReadyException();
       }
-      var floatData = _buffer.asByteData(_index, 4);
+      var floatData = _underlyingData.buffer.asByteData(_index, 4);
       _index += 4;
       return floatData.getFloat32(0, Endian.little);
     } else {
-      if ((_buffer.lengthInBytes - index) < 4) {
+      if ((_bufferSize - index) < 4) {
         throw NotReadyException();
       }
-      var floatData = _buffer.asByteData(index, 4);
+      var floatData = _underlyingData.buffer.asByteData(index, 4);
       _index = index + 4;
       return floatData.getFloat32(0, Endian.little);
     }
@@ -264,17 +271,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 8) {
+      if ((_bufferSize - _index) < 8) {
         throw NotReadyException();
       }
-      var floatData = _buffer.asByteData(_index, 8);
+      var floatData = _underlyingData.buffer.asByteData(_index, 8);
       _index += 8;
       return floatData.getFloat64(0, Endian.little);
     } else {
-      if ((_buffer.lengthInBytes - index) < 8) {
+      if ((_bufferSize - index) < 8) {
         throw NotReadyException();
       }
-      var floatData = _buffer.asByteData(index, 8);
+      var floatData = _underlyingData.buffer.asByteData(index, 8);
       _index = index + 8;
       return floatData.getFloat64(0, Endian.little);
     }
@@ -286,17 +293,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 1) {
+      if ((_bufferSize - _index) < 1) {
         throw NotReadyException();
       }
-      var boolData = _buffer.asByteData(_index, 1);
+      var boolData = _underlyingData.buffer.asByteData(_index, 1);
       _index++;
       return boolData.getInt8(0) == 1;
     } else {
-      if ((_buffer.lengthInBytes - index) < 1) {
+      if ((_bufferSize - index) < 1) {
         throw NotReadyException();
       }
-      var boolData = _buffer.asByteData(index, 1);
+      var boolData = _underlyingData.buffer.asByteData(index, 1);
       _index = index + 1;
       return boolData.getInt8(0) == 1;
     }
@@ -308,17 +315,17 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     if (index == -1) {
-      if ((_buffer.lengthInBytes - _index) < 1) {
+      if ((_bufferSize - _index) < 1) {
         throw NotReadyException();
       }
-      var byteData = _buffer.asByteData(_index, 1);
+      var byteData = _underlyingData.buffer.asByteData(_index, 1);
       _index++;
       return byteData.getInt8(0);
     } else {
-      if ((_buffer.lengthInBytes - index) < 1) {
+      if ((_bufferSize - index) < 1) {
         throw NotReadyException();
       }
-      var byteData = _buffer.asByteData(index, 1);
+      var byteData = _underlyingData.buffer.asByteData(index, 1);
       _index = index + 1;
       return byteData.getInt8(0);
     }
@@ -330,10 +337,10 @@ class VidUsDataHttpReader {
       throw DownloadErrorException(_errorMsg);
     }
     var dataLength = readInt(index);
-    if ((_buffer.lengthInBytes - _index) < dataLength) {
+    if ((_bufferSize - _index) < dataLength) {
       throw NotReadyException();
     }
-    var bytes = _buffer.asUint8List(_index, dataLength);
+    var bytes = _underlyingData.buffer.asUint8List(_index, dataLength);
     _index += dataLength;
     return bytes;
   }

+ 38 - 18
lib/us/vid_us_image_data.dart

@@ -76,6 +76,8 @@ class VidUsImageData {
 
 class ReadTimeoutException implements Exception {}
 
+class AlreadyClosedException implements Exception {}
+
 ///Only suport read for now.
 ///Not suport carotid3d for now.
 class HttpVidUsImageData {
@@ -86,7 +88,9 @@ class HttpVidUsImageData {
   late VidUsProbe _probe;
   late VidUsImageFormat _imageFormat;
   late Uint8List _extendedData;
-  late int _readTimeout;
+  late int _readHeaderTimeout;
+  late int _readImageTimeout;
+  late bool _closed;
 
   final Duration delayDuration = const Duration(milliseconds: 10);
   final String header = "VINNO IMAGE DATA";
@@ -107,8 +111,12 @@ class HttpVidUsImageData {
   Uint8List get extendedData => _extendedData;
 
   /// Create a VINNO Image Data.
-  HttpVidUsImageData(String url, {DownloadCallback? downloadCallback, int readTimeout = 1000}) {
-    _readTimeout = readTimeout;
+  /// [readHeaderTimeout] is the timeout value of reading header and probe information etc...
+  /// [readImageTimeout] is the timeout value of reading one frame.
+  HttpVidUsImageData(String url, {DownloadCallback? downloadCallback, int readHeaderTimeout = 1000, int readImageTimeout = 300}) {
+    _closed = false;
+    _readHeaderTimeout = readHeaderTimeout;
+    _readImageTimeout = readImageTimeout;
     _reader = VidUsDataHttpReader(url, downloadCallback: downloadCallback);
   }
 
@@ -132,16 +140,21 @@ class HttpVidUsImageData {
     }
   }
 
+  void close() {
+    _closed = true;
+    _reader.close();
+  }
+
   //Read header from http data.
   Future<String> _readHeader() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         var header = _reader.readString();
         return header;
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -151,18 +164,19 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
   //Read the version from http data.
   Future<int> _readVersion() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         var version = _reader.readInt();
         return version;
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -172,18 +186,19 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
   //Read the probe info from http data.
   Future<VidUsProbe> _readProbe() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         var probeData = _reader.readBytes();
         return VidUsProbe.fromBytes(probeData);
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -193,17 +208,18 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
   //Read the image format from http data.
   Future<VidUsImageFormat> _readImageFormat() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         return VidUsImageFormat.values[_reader.readInt()];
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -213,17 +229,18 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
   //Read extended data from http data.
   Future<Uint8List> _readExtendedData() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         return _reader.readBytes();
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -233,17 +250,18 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
-  //Read the image positions data from http data. 
+  //Read the image positions data from http data.
   Future<Uint8List> _readImagePositionListData() async {
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         return _reader.readBytes();
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readHeaderTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -253,6 +271,7 @@ class HttpVidUsImageData {
         }
       }
     }
+    throw AlreadyClosedException();
   }
 
   /// Get one image from the vid.
@@ -262,13 +281,13 @@ class HttpVidUsImageData {
     }
     //Jump to image.
     var timeout = 0;
-    while (true) {
+    while (!_closed) {
       try {
         var imageData = _reader.readBytes(_imagePositionList[index]);
         return VidUsImage.fromBytes(imageData);
       } catch (ex) {
         if (ex is NotReadyException) {
-          if (timeout >= _readTimeout) {
+          if (timeout >= _readImageTimeout) {
             throw ReadTimeoutException();
           }
           await Future.delayed(delayDuration);
@@ -278,5 +297,6 @@ class HttpVidUsImageData {
         }
       }
     }
+      throw AlreadyClosedException();
   }
 }