diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index d8a56a06..db043bfb 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -368,7 +368,7 @@
-
+
@@ -3216,19 +3216,19 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index 026ed9a5..b612e756 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -1925,7 +1925,7 @@
-
+
@@ -3106,16 +3106,16 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings
index f71a2a3b..313166b6 100644
--- a/VoidLink/Localization/Localizable.xcstrings
+++ b/VoidLink/Localization/Localizable.xcstrings
@@ -3577,7 +3577,7 @@
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
- "value" : "- 关闭 = 无帧步进控制,即为之前的“最低延迟”.\n\n- 传统模式,相当于之前的“最高流畅度” (尽管已经不是最流畅的选项)."
+ "value" : "- 关闭 = 无帧步进控制,即为moonlight的“最低延迟”.\n\n- 传统模式,相当于之前的“最高流畅度” (尽管已经不是最流畅的选项)."
}
},
"zh-Hant" : {
@@ -4481,6 +4481,29 @@
}
}
},
+ "lowest latency" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "最低延迟"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "最低延遲"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "最低延遲"
+ }
+ }
+ }
+ },
"Manual_Add_Host_Fail" : {
"extractionState" : "manual",
"localizations" : {
diff --git a/VoidLink/Stream/StreamManager.m b/VoidLink/Stream/StreamManager.m
index 5e42dc16..29f54e1e 100644
--- a/VoidLink/Stream/StreamManager.m
+++ b/VoidLink/Stream/StreamManager.m
@@ -115,6 +115,7 @@
}
- (void) setNeedRequeuing:(bool)needRequeuing{
+ if (_videoRenderer.queueSize==0) return;
[_videoRenderer.frameQueue clear];
_videoRenderer.needRequeuing = needRequeuing;
}
diff --git a/VoidLink/Stream/VideoDecoderRenderer.h b/VoidLink/Stream/VideoDecoderRenderer.h
index fcc10e7c..3dc14832 100644
--- a/VoidLink/Stream/VideoDecoderRenderer.h
+++ b/VoidLink/Stream/VideoDecoderRenderer.h
@@ -20,6 +20,7 @@
@property (atomic, readonly) PlotMetrics frameQueueMetrics;
@property (atomic, assign) bool needRequeuing;
@property (nonatomic, strong) FrameQueue* frameQueue;
+@property (atomic, readonly) int32_t queueSize;
@property (nonatomic, strong, readonly) AVSampleBufferDisplayLayer *displayLayer;
diff --git a/VoidLink/Stream/VideoDecoderRenderer.m b/VoidLink/Stream/VideoDecoderRenderer.m
index b7d6595d..3c3c6e5c 100644
--- a/VoidLink/Stream/VideoDecoderRenderer.m
+++ b/VoidLink/Stream/VideoDecoderRenderer.m
@@ -52,7 +52,6 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
VTDecompressionSessionRef _decompressionSession;
CADisplayLink *_displayLink;
- uint8_t queueSize;
NSInteger _maxRefreshRate;
RenderingBackend _renderingBackend;
@@ -145,13 +144,13 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
_asyncFrameDequeue = tempSettings.asyncFrameDequeue;
NSLog(@"_asyncFrameDequeue %d", _asyncFrameDequeue);
_enableTimebase = false;
- queueSize = tempSettings.frameQueueSize.intValue;
- _needRequeuing = true;
+ _queueSize = tempSettings.frameQueueSize.intValue;
+ _needRequeuing = _queueSize>0;
isIPhone = [Utils isIPhone];
_frameQueue = [FrameQueue sharedInstance];
[_frameQueue start];
- [_frameQueue setHighWaterMark:(int)[tempSettings.frameQueueSize integerValue]];
+ [_frameQueue setHighWaterMark:MAX(1, _queueSize)];
[self reinitializeDisplayLayer];
// NSTimeInterval interval = 1.0/tempSettings.framerate.intValue;
@@ -310,8 +309,8 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
waitFor = 0.0f;
}
*/
-
- if(_needRequeuing ? _frameQueue.count>queueSize-1 : true){
+
+ if(_needRequeuing ? _frameQueue.count>MAX(_queueSize-1,0) : true){
// if(true){
_needRequeuing = false;
if(_asyncFrameDequeue){
diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m
index d1622d6b..0d1ed02e 100644
--- a/VoidLink/ViewControllers/MainFrameViewController.m
+++ b/VoidLink/ViewControllers/MainFrameViewController.m
@@ -1170,7 +1170,7 @@ static NSMutableSet* hostList;
self.navigationItem.leftBarButtonItems = @[_settingsButton];
if(streamFrameViewController.streamMan){
- NSLog(@"setNeedRequeuing %f", CACurrentMediaTime());
+ // NSLog(@"setNeedRequeuing %f", CACurrentMediaTime());
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^{
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 51173ccc..9c887e00 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -1994,7 +1994,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self updateBitrateText];
[self updateResolutionDisplayLabel];
- [self.frameQueueSizeSlider setMinimumValue:1];
+ [self.frameQueueSizeSlider setMinimumValue:0];
[self.frameQueueSizeSlider setMaximumValue:5];
[self.frameQueueSizeSlider setValue:self->tempSettings.frameQueueSize.intValue];
[self.frameQueueSizeSlider addTarget:self action:@selector(frameQueueSizeSliderMoved:) forControlEvents:UIControlEventValueChanged];
@@ -3381,7 +3381,8 @@ BOOL isCustomResolution(int resolutionSelected) {
- (void) frameQueueSizeSliderMoved:(UISlider* )sender {
assert(self.frameQueueSizeSlider.value >= 0 && self.frameQueueSizeSlider.value <= 5);
- [self findDynamicLabelFromStack:_frameQueueSizeStack].text = [NSString stringWithFormat:@" %d ", (int)self.frameQueueSizeSlider.value];
+ int queueSize = self.frameQueueSizeSlider.value;
+ [self findDynamicLabelFromStack:_frameQueueSizeStack].text = queueSize==0 ? [LocalizationHelper localizedStringForKey:@"lowest latency"] : [NSString stringWithFormat: @" %d ", queueSize];
}
- (void) enableGraphsChanged:(UISwitch* )sender {