feat: add back lowest latency mode for AVSampleBuffer
This commit is contained in:
@@ -1000,6 +1000,7 @@
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="2Dp-Qg-chi" userLabel="Frame Pacing Mode Selector">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Off"/>
|
||||
<segment title="Legacy"/>
|
||||
<segment title="Queue Buffering"/>
|
||||
</segments>
|
||||
|
||||
@@ -1695,6 +1695,7 @@
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="CC6-pu-Uoh" userLabel="Frame Pacing Mode Selector">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Off"/>
|
||||
<segment title="Legacy"/>
|
||||
<segment title="Queue Buffering"/>
|
||||
</segments>
|
||||
|
||||
@@ -43,6 +43,7 @@ typedef NS_ENUM(NSInteger, GyroMode) {
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, FramePacingMode) {
|
||||
FramePacingModeOff,
|
||||
FramePacingModeLegacy,
|
||||
FramePacingModeQueue
|
||||
};
|
||||
|
||||
@@ -493,9 +493,10 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t
|
||||
LiInitializeVideoCallbacks(&_drCallbacks);
|
||||
_drCallbacks.setup = DrDecoderSetup;
|
||||
_drCallbacks.cleanup = DrCleanup;
|
||||
// Use pull renderer for legacy frame pacing, direct submit for modern frame pacing
|
||||
// Use pull renderer for legacy and off frame pacing, direct submit for queue-based frame pacing
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
if ([[dataMan getSettings].framePacingMode integerValue] == FramePacingModeLegacy) {
|
||||
FramePacingMode framePacingMode = [[dataMan getSettings].framePacingMode integerValue];
|
||||
if (framePacingMode == FramePacingModeLegacy || framePacingMode == FramePacingModeOff) {
|
||||
_drCallbacks.capabilities = CAPABILITY_PULL_RENDERER |
|
||||
CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC |
|
||||
CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1;
|
||||
|
||||
@@ -189,13 +189,13 @@
|
||||
|
||||
float interval = stats.endTime - stats.startTime;
|
||||
|
||||
// Check if we're using legacy pacing mode
|
||||
// Get frame pacing mode
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
BOOL isLegacyPacing = [[dataMan getSettings].framePacingMode integerValue] == FramePacingModeLegacy;
|
||||
|
||||
FramePacingMode framePacingMode = [[dataMan getSettings].framePacingMode integerValue];
|
||||
|
||||
// Calculate FPS differently based on pacing mode
|
||||
float fps;
|
||||
if (isLegacyPacing) {
|
||||
if (framePacingMode == FramePacingModeLegacy || framePacingMode == FramePacingModeOff) {
|
||||
fps = stats.totalFrames / interval;
|
||||
} else {
|
||||
float scalePlotMetrics = stats.frameDropMetrics.nsamples > 0 ? ((float)stats.frameDropMetrics.nsamples / stats.totalFrames) : 1.0f;
|
||||
@@ -210,10 +210,14 @@
|
||||
stats.networkDroppedFrames / interval,
|
||||
latencyString];
|
||||
else {
|
||||
if (isLegacyPacing) {
|
||||
if (framePacingMode == FramePacingModeLegacy || framePacingMode == FramePacingModeOff) {
|
||||
NSString* rendererWithPacing = stats.renderingBackendString;
|
||||
if ([stats.renderingBackendString isEqualToString:@"AVSampleBuffer"]) {
|
||||
rendererWithPacing = @"AVSampleBuffer (Legacy Pacing)";
|
||||
if (framePacingMode == FramePacingModeOff) {
|
||||
rendererWithPacing = @"AVSampleBuffer (No Pacing)";
|
||||
} else {
|
||||
rendererWithPacing = @"AVSampleBuffer (Legacy Pacing)";
|
||||
}
|
||||
}
|
||||
|
||||
return [LocalizationHelper localizedStringForKey:@"Video stream: %dx%d %.2f FPS (Codec: %@)\n"
|
||||
|
||||
@@ -55,7 +55,7 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
|
||||
NSInteger _maxRefreshRate;
|
||||
RenderingBackend _renderingBackend;
|
||||
|
||||
BOOL _useLegacyPacing;
|
||||
FramePacingMode _framePacingMode;
|
||||
}
|
||||
|
||||
- (void)reinitializeDisplayLayer
|
||||
@@ -130,7 +130,7 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
|
||||
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
|
||||
_useLegacyPacing = [[dataMan getSettings].framePacingMode integerValue] == FramePacingModeLegacy;
|
||||
_framePacingMode = [[dataMan getSettings].framePacingMode integerValue];
|
||||
|
||||
_frameQueue = [FrameQueue sharedInstance];
|
||||
[_frameQueue start];
|
||||
@@ -162,8 +162,8 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
|
||||
|
||||
// Choose the appropriate selector based on frame pacing mode
|
||||
SEL displayLinkSelector;
|
||||
if (_useLegacyPacing) {
|
||||
// Legacy frame pacing: use simple displayLinkCallback
|
||||
if (_framePacingMode == FramePacingModeLegacy || _framePacingMode == FramePacingModeOff) {
|
||||
// Legacy frame pacing or Off mode: use simple displayLinkCallback
|
||||
displayLinkSelector = @selector(displayLinkCallback:);
|
||||
} else {
|
||||
// PACING_MODE_VSYNC:
|
||||
@@ -332,21 +332,22 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
|
||||
while (LiPollNextVideoFrame(&handle, &du)) {
|
||||
LiCompleteVideoFrame(handle, DrSubmitDecodeUnit(du));
|
||||
|
||||
/*
|
||||
// Calculate the actual display refresh rate
|
||||
double displayRefreshRate = 1 / (_displayLink.targetTimestamp - _displayLink.timestamp);
|
||||
|
||||
// Only pace frames if the display refresh rate is >= 90% of our stream frame rate.
|
||||
// Battery saver, accessibility settings, or device thermals can cause the actual
|
||||
// refresh rate of the display to drop below the physical maximum.
|
||||
if (displayRefreshRate >= _frameRate * 0.9f) {
|
||||
// Keep one pending frame to smooth out gaps due to
|
||||
// network jitter at the cost of 1 frame of latency
|
||||
if (LiGetPendingVideoFrames() == 1) {
|
||||
break;
|
||||
// Skip frame pacing logic if frame pacing is off
|
||||
if (_framePacingMode != FramePacingModeOff) {
|
||||
// Calculate the actual display refresh rate
|
||||
double displayRefreshRate = 1 / (_displayLink.targetTimestamp - _displayLink.timestamp);
|
||||
|
||||
// Only pace frames if the display refresh rate is >= 90% of our stream frame rate.
|
||||
// Battery saver, accessibility settings, or device thermals can cause the actual
|
||||
// refresh rate of the display to drop below the physical maximum.
|
||||
if (displayRefreshRate >= _frameRate * 0.9f) {
|
||||
// Keep one pending frame to smooth out gaps due to
|
||||
// network jitter at the cost of 1 frame of latency
|
||||
if (LiGetPendingVideoFrames() == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,7 +859,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
|
||||
|
||||
CMSampleBufferRef sampleBuffer;
|
||||
CMTime presentationTimeStamp;
|
||||
if (_useLegacyPacing) {
|
||||
if (_framePacingMode == FramePacingModeLegacy || _framePacingMode == FramePacingModeOff) {
|
||||
presentationTimeStamp = CMTimeMake(du->presentationTimeUs / 1000, 1000);
|
||||
} else {
|
||||
presentationTimeStamp = CMTimeMake((int64_t)du->rtpTimestamp, 90000);
|
||||
@@ -883,7 +884,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
if (_useLegacyPacing) {
|
||||
if (_framePacingMode == FramePacingModeLegacy || _framePacingMode == FramePacingModeOff) {
|
||||
// Enqueue the next frame
|
||||
[self->_displayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
|
||||
|
||||
@@ -1745,16 +1745,17 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
- (void)framePacingModeChanged:(UISegmentedControl *)sender {
|
||||
[self setHidden:sender.selectedSegmentIndex == FramePacingModeLegacy forStack:self.frameQueueSizeStack];
|
||||
// Hide frame queue size for Off and Legacy modes
|
||||
[self setHidden:(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy) forStack:self.frameQueueSizeStack];
|
||||
[videoSection updateViewForFoldState];
|
||||
|
||||
if(sender.selectedSegmentIndex == FramePacingModeLegacy){
|
||||
if(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy){
|
||||
[self.enableGraphsSwitch setOn:NO];
|
||||
[self findDynamicLabelFromStack:_graphOpacityStack].hidden = YES;
|
||||
}
|
||||
[self.enableGraphsSwitch setEnabled:sender.selectedSegmentIndex == FramePacingModeQueue];
|
||||
[self.graphOpacityStepper setEnabled:self.enableGraphsSwitch.isOn];
|
||||
[self setHidden:sender.selectedSegmentIndex == FramePacingModeLegacy forStack:self.performanceGraphStack];
|
||||
[self setHidden:(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy) forStack:self.performanceGraphStack];
|
||||
[otherSection updateViewForFoldState];
|
||||
|
||||
/*
|
||||
|
||||
@@ -32,7 +32,37 @@
|
||||
}
|
||||
},
|
||||
"2Dp-Qg-chi.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; 2Dp-Qg-chi.segmentTitles[0] = \"Legacy\"; ObjectID = \"2Dp-Qg-chi\";",
|
||||
"comment" : "Class = \"UISegmentedControl\"; 2Dp-Qg-chi.segmentTitles[0] = \"Off\"; ObjectID = \"2Dp-Qg-chi\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Off"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "关闭"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "關閉"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "關閉"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"2Dp-Qg-chi.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; 2Dp-Qg-chi.segmentTitles[1] = \"Legacy\"; ObjectID = \"2Dp-Qg-chi\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -61,8 +91,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"2Dp-Qg-chi.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; 2Dp-Qg-chi.segmentTitles[1] = \"Queue Buffering\"; ObjectID = \"2Dp-Qg-chi\";",
|
||||
"2Dp-Qg-chi.segmentTitles[2]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; 2Dp-Qg-chi.segmentTitles[2] = \"Queue Buffering\"; ObjectID = \"2Dp-Qg-chi\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
||||
@@ -1058,7 +1058,38 @@
|
||||
}
|
||||
},
|
||||
"CC6-pu-Uoh.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; CC6-pu-Uoh.segmentTitles[0] = \"Legacy\"; ObjectID = \"CC6-pu-Uoh\";",
|
||||
"comment" : "Class = \"UISegmentedControl\"; CC6-pu-Uoh.segmentTitles[0] = \"Off\"; ObjectID = \"CC6-pu-Uoh\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Off"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "关闭"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "關閉"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "關閉"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
"CC6-pu-Uoh.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; CC6-pu-Uoh.segmentTitles[1] = \"Legacy\"; ObjectID = \"CC6-pu-Uoh\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -1087,8 +1118,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"CC6-pu-Uoh.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; CC6-pu-Uoh.segmentTitles[1] = \"Queue Buffering\"; ObjectID = \"CC6-pu-Uoh\";",
|
||||
"CC6-pu-Uoh.segmentTitles[2]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; CC6-pu-Uoh.segmentTitles[2] = \"Queue Buffering\"; ObjectID = \"CC6-pu-Uoh\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
||||
Reference in New Issue
Block a user