123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- import 'dart:async';
- import 'dart:math' as math;
- import 'package:fis_common/logger/logger.dart';
- import 'package:fis_vid/data_channel/channel.dart';
- class VidBufferWaiter {
- VidBufferWaiter(
- this.channel, {
- this.timeout = 10 * 1000,
- });
-
- static const _FIRST_FRAME_LOAD_TIME_LIMIT = 60 * 1000;
-
- final VidDataChannel channel;
-
- final int timeout;
- double _frameRate = 0;
- int _frameCount = 0;
- int _framePerSize = 0;
- int _vidHeadSize = 0;
- int _maxDuration = 0;
- Timer? _timer;
-
- int get vidHeaderSize => _vidHeadSize;
-
- void init() {
- _frameRate = channel.probe.frameRate;
- _frameCount = channel.imageCount;
- _vidHeadSize = _calcHeaderSize();
- _framePerSize = _calcFramePerSize();
- }
-
- Future<void> waitSingleVid() async {
- logger.i("VidPlayer - Wait single vid start.");
- final completer = Completer();
- const int waitInterval = 100;
- const int waitCountLimit = _FIRST_FRAME_LOAD_TIME_LIMIT ~/ waitInterval;
- int waitCount = 0;
- _timer = Timer.periodic(
- const Duration(milliseconds: waitInterval),
- (timer) {
- waitCount++;
- if (channel.isBufferedDone) {
-
- timer.cancel();
- completer.complete();
- logger.i("VidPlayer - Wait single vid end.");
- return;
- }
- if (waitCount >= waitCountLimit) {
- completer.completeError(Exception("First frame load timeout"));
- logger.i("VidPlayer - Wait single vid: timeout.");
- }
- },
- );
- return completer.future;
- }
-
- Future<void> waitBuffer(int frameIndex) {
- logger.i("VidPlayer - Wait buffer start.");
- final completer = Completer();
- final bufferredSize = channel.getBufferSize();
- final needBufferSize = _calcNeedWaitSize(frameIndex);
- const int waitInterval = 100;
- final int waitCountLimit = timeout ~/ waitInterval;
- int waitCount = 0;
- final startTime = DateTime.now();
- _timer = Timer.periodic(
- const Duration(milliseconds: waitInterval),
- (timer) {
-
- void finishFn() {
- timer.cancel();
- completer.complete();
- final endTime = DateTime.now();
- final spendTime = endTime.difference(startTime).inMilliseconds;
- logger.i("VidPlayer - Wait buffer end, spend time: $spendTime ms.");
- }
- waitCount++;
- final bufferedSize = channel.getBufferSize();
- if (bufferedSize >= needBufferSize) {
-
- return finishFn();
- }
- if (waitCount >= waitCountLimit) {
-
- final bufferredSizeNow = channel.getBufferSize();
- if (bufferredSizeNow - bufferredSize < 1024) {
-
- completer.completeError(Exception("Wait buffer timeout"));
- logger.i("VidPlayer - Wait buffer timeout.");
- } else {
-
- finishFn();
- }
- }
- },
- );
- return completer.future;
- }
-
- void recordFrameSpendTime(int millseconds) {
- _maxDuration = math.max(_maxDuration, millseconds);
- }
-
- void cancel() {
- _timer?.cancel();
- }
- int _calcNeedWaitSize(int frameIndex) {
- int needWaitSize = 0;
- final int bufferedSize = channel.getBufferSize();
- final int totalSize = channel.getFileSize();
-
- final int bufferredFrameCount = bufferedSize ~/ _framePerSize;
-
- final int unbufferredFrameCount = _frameCount - bufferredFrameCount;
-
- final int unbufferredSize = totalSize - bufferedSize;
-
- final int needBufferTime = unbufferredFrameCount * _maxDuration;
-
- final int unbufferredDuration =
- ((1000 / _frameRate) * unbufferredFrameCount).toInt();
-
- final int perSecondNeedSize = (_framePerSize * _frameRate).toInt();
-
- int needWaitTime = needBufferTime - unbufferredDuration;
- if (needWaitTime < 0) {
-
-
- needWaitSize = perSecondNeedSize;
- } else {
- needWaitTime += 1;
- needWaitSize = needWaitTime * perSecondNeedSize;
- if (frameIndex > bufferredFrameCount) {
-
- final needWaitExtraCount = frameIndex - bufferredFrameCount;
- final needWaitExtraSize = _framePerSize * needWaitExtraCount;
- needWaitSize += needWaitExtraSize;
- }
- }
- return math.max(unbufferredSize, needWaitSize);
- }
- int _calcFramePerSize() {
- final size = _calcFramesBytesSize();
- final perSize = size ~/ channel.imageCount;
- return perSize;
- }
- int _calcFramesBytesSize() {
- int size = channel.getFileSize();
- size -= _vidHeadSize;
- return size;
- }
- int _calcHeaderSize() {
- int size = 0;
- size += channel.probe.toBytes().length;
- size += channel.extendedData.length;
- size += channel.imageCount * 8;
- size += 16;
- size += 4;
- size += 4;
- return size;
- }
- }
|