refactor: use separate piplayer for AVSB pip function

This commit is contained in:
Acaki committed 2025-07-16 01:17:28 +08:00
1 parent 5a2d5af887
commit bd9e2e3215
2 files changed
+30 -19

No files matched your search

+18 -6
View File
@@ -852,11 +852,10 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
LiRequestIdrFrame(); // Request an IDR to restart the stream LiRequestIdrFrame(); // Request an IDR to restart the stream
return; return;
} }
if (self->_renderingBackend == RENDER_METAL && self.pipLayer) {
// NSLog(@"[Metal PiP Path] Entered for frame number %d.", frameNumber); if (self.pipLayer) {
CVPixelBufferRetain(imageBuffer); CVPixelBufferRetain(imageBuffer);
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"[Metal PiP Path] Executing on main thread for frame %d.", frameNumber);
@synchronized(self) { @synchronized(self) {
if (self.pipLayer.controlTimebase == NULL) { if (self.pipLayer.controlTimebase == NULL) {
NSLog(@"[Metal PiP Path] Timebase is NULL. Setting it now."); NSLog(@"[Metal PiP Path] Timebase is NULL. Setting it now.");
@@ -886,7 +885,6 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
CMSampleTimingInfo sampleTiming = {kCMTimeInvalid, presentationTimestamp, presentationDuration}; CMSampleTimingInfo sampleTiming = {kCMTimeInvalid, presentationTimestamp, presentationDuration};
OSStatus err = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, imageBuffer, self->_pipFormatDesc, &sampleTiming, &sampleBufferForPip); OSStatus err = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, imageBuffer, self->_pipFormatDesc, &sampleTiming, &sampleBufferForPip);
if (err == noErr && sampleBufferForPip) { if (err == noErr && sampleBufferForPip) {
// NSLog(@"[Metal PiP Path] Sample buffer created. Enqueuing to _pipLayer.");
[self.pipLayer enqueueSampleBuffer:sampleBufferForPip]; [self.pipLayer enqueueSampleBuffer:sampleBufferForPip];
CFRelease(sampleBufferForPip); CFRelease(sampleBufferForPip);
} else { } else {
@@ -899,7 +897,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
} }
// --- MAIN RENDERER PATH --- // --- MAIN RENDERER PATH ---
if (self->_renderingBackend == RENDER_AVSB) { if (self->_renderingBackend == RENDER_AVSB) {
// self.pipLayer.hidden = YES; self.pipLayer.hidden = NO;
if (self->_avsbFormatDesc == NULL || !CMVideoFormatDescriptionMatchesImageBuffer(self->_avsbFormatDesc, imageBuffer)) { if (self->_avsbFormatDesc == NULL || !CMVideoFormatDescriptionMatchesImageBuffer(self->_avsbFormatDesc, imageBuffer)) {
if (self->_avsbFormatDesc) { if (self->_avsbFormatDesc) {
CFRelease(self->_avsbFormatDesc); CFRelease(self->_avsbFormatDesc);
@@ -915,7 +913,21 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
dispatch_async(self->_vtq, ^{ dispatch_async(self->_vtq, ^{
Frame *frame = [[Frame alloc] initWithSampleBuffer:sampleBufferForAvsb frameNumber:frameNumber frameType:frameType]; Frame *frame = [[Frame alloc] initWithSampleBuffer:sampleBufferForAvsb frameNumber:frameNumber frameType:frameType];
int framesDropped = [self->_frameQueue enqueue:frame withSlackSize:3]; int framesDropped = [self->_frameQueue enqueue:frame withSlackSize:3];
// ... stats and metrics updates static PlotMetrics frameQueueMetrics = {};
[[ImGuiPlots sharedInstance] observeFloatReturnMetrics:PLOT_QUEUED_FRAMES value:[self->_frameQueue count] plotMetrics:&frameQueueMetrics];
[self safeCopyMetricsTo:&self->_frameQueueMetrics from:&frameQueueMetrics];
[[ImGuiPlots sharedInstance] observeFloat:PLOT_DROPPED value:framesDropped];
static CFTimeInterval lastHostFrame = 0.0f;
if (lastHostFrame != 0) {
[[ImGuiPlots sharedInstance] observeFloat:PLOT_HOST_FRAMETIME value:(frame.pts - lastHostFrame) * 1000.0];
}
lastHostFrame = frame.pts;
static PlotMetrics decodeMetrics = {};
[[ImGuiPlots sharedInstance] observeFloatReturnMetrics:PLOT_DECODE value:(CACurrentMediaTime() - decodeStartTime) * 1000.0 plotMetrics:&decodeMetrics];
[self safeCopyMetricsTo:&self->_decodeMetrics from:&decodeMetrics];
}); });
} else { } else {
if (sampleBufferForAvsb) { if (sampleBufferForAvsb) {
@@ -97,6 +97,7 @@
- (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { - (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
_streamView.hidden = YES; _streamView.hidden = YES;
_pipLayer.hidden = YES;
if (self.imguiView) { if (self.imguiView) {
self.imguiView.mtkView.hidden = YES; self.imguiView.mtkView.hidden = YES;
Log(LOG_I, @"Hiding ImGui view for PiP start."); Log(LOG_I, @"Hiding ImGui view for PiP start.");
@@ -116,6 +117,7 @@
- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { - (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
_streamView.hidden = NO; _streamView.hidden = NO;
_pipLayer.hidden = NO;
if (self.imguiView) { if (self.imguiView) {
self.imguiView.mtkView.hidden = NO; self.imguiView.mtkView.hidden = NO;
Log(LOG_I, @"Showing ImGui view after PiP stop."); Log(LOG_I, @"Showing ImGui view after PiP stop.");
@@ -129,6 +131,7 @@
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler { - (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler {
_isRestoringFromPiP = YES; _isRestoringFromPiP = YES;
_streamView.hidden = NO; _streamView.hidden = NO;
_pipLayer.hidden = NO;
if (self.imguiView) { if (self.imguiView) {
self.imguiView.mtkView.hidden = NO; self.imguiView.mtkView.hidden = NO;
Log(LOG_I, @"Showing ImGui view for PiP restore."); Log(LOG_I, @"Showing ImGui view for PiP restore.");
@@ -178,27 +181,23 @@
return (_settings.touchMode.intValue == RelativeTouch || _settings.touchMode.intValue == NativeTouch || _settings.touchMode.intValue == AbsoluteTouch) && _settings.onscreenControls.intValue == OnScreenControlsLevelCustom; return (_settings.touchMode.intValue == RelativeTouch || _settings.touchMode.intValue == NativeTouch || _settings.touchMode.intValue == AbsoluteTouch) && _settings.onscreenControls.intValue == OnScreenControlsLevelCustom;
} }
- (void)setupPiPControllerWithRenderer:(VideoDecoderRenderer *)videoRenderer { // Ensure we have the renderer and its layer - (void)setupPiPControllerWithRenderer:(VideoDecoderRenderer *)videoRenderer {
if (self.pipController) { if (self.pipController) {
return; return;
} }
Log(LOG_I, @"Setting up PiP controller..."); Log(LOG_I, @"Setting up PiP controller...");
AVSampleBufferDisplayLayer* sourceLayer; // Both Metal and AVSB will use the dedicated _pipLayer for PiP.
AVSampleBufferDisplayLayer* sourceLayer = _pipLayer;
if ([_settings.renderingBackend intValue] == RENDER_METAL) { if ([_settings.renderingBackend intValue] == RENDER_METAL) {
sourceLayer = _pipLayer; NSLog(@"[PiP LOG] Backend: Metal. Using dedicated _pipLayer: %p", sourceLayer);
NSLog(@"[PiP LOG] Backend: Metal. Using _pipLayer: %p", sourceLayer);
if (!sourceLayer) {
NSLog(@"[PiP LOG] ERROR: _pipLayer is nil during setup.");
return;
}
} else { // RENDER_AVSB } else { // RENDER_AVSB
sourceLayer = videoRenderer.displayLayer; NSLog(@"[PiP LOG] Backend: AVSB. Using dedicated _pipLayer: %p", sourceLayer);
NSLog(@"[PiP LOG] Backend: AVSB. Using _displayLayer: %p", sourceLayer);
} }
if (!_pipLayer) { if (!sourceLayer) {
Log(LOG_E, @"PiP setup failed: Dedicated PiP layer not ready."); Log(LOG_E, @"PiP setup failed: Dedicated PiP layer is nil.");
return; return;
} }