import 'dart:async'; import 'package:fis_common/event/event_type.dart'; import 'package:fis_vid/async_vid/vid_data.dart'; import 'package:flutter/foundation.dart'; import 'package:vid/us/vid_us_data_http_reader.dart'; import 'package:vid/us/vid_us_image.dart'; import 'package:vid/us/vid_us_image_data.dart'; import 'package:vid/us/vid_us_probe.dart'; import 'channel_stub.dart' if (dart.library.html) 'channel_web.dart' if (dart.library.io) 'channel_io.dart'; import 'progress_info.dart'; abstract class VidDataChannel { @protected late final AsyncVidImageDataBase? source; final String url; VidDataChannel(this.url); factory VidDataChannel.create(String url) { return VidDataChannelImpl(url); } /// 下载进度变更事件 final downloadProgressChanged = FEventHandler(); bool _initialized = false; /// 是否初始化完成 bool get initialized => _initialized; /// 开始加载数据 /// /// [timeout] 超时时间,单位ms, 默认5s Future load([int timeout = 5 * 1000]) async { if (_initialized) return true; try { final completer = Completer(); final timer = Timer( Duration(milliseconds: timeout), () { if (!completer.isCompleted) { completer.complete(_initialized); } if (!_initialized) { source?.close(); } }, ); _innerLoad(timeout).then((value) { _initialized = true; if (timer.isActive) { timer.cancel(); } completer.complete(true); }); return completer.future; } catch (e) { return false; } } /// 分发下载进度回调 @protected void onDownloadCallback(double progress, DownloadErrorException? error) { final info = VidDownloadProgressInfo(progress, error: error); downloadProgressChanged.emit(this, info); } Future _innerLoad(int timeout) async { try { source = await buildSource(); source!.setReadHeaderTimeout(timeout + 50); // 50ms buffer 4 timer await source!.initialize(); return true; } catch (e) { return false; } } ///获取缓冲量 int getBufferSize() { return source!.getReader().downloadedSize; } /// 获取文件尺寸 int getFileSize() { return source!.getReader().totalSize; } /// 是否缓冲完成 bool get isBufferedDone { return getBufferSize() >= getFileSize(); } VidUsProbe get probe => source!.probe; int get imageCount => source!.imageCount; VidUsImageFormat get imageFormat => source!.imageFormat; Uint8List get extendedData => source!.extendedData; /// 获取指定帧 /// /// [index] 帧索引 /// /// [timeout] 超时时间ms Future getImage(int index, [int timeout = 500]) async { source!.setReadImageTimeout(timeout); return source!.getImage(index); } /// 关闭通道 void close() { _initialized = false; try { source?.close(); } catch (e) {} } @protected Future buildSource(); }