From 4a9e109de590a85aac2e90008aa715c83d1230dd Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Sat, 25 Oct 2025 13:57:36 +0800 Subject: [PATCH] stop video render when app enters background without pip enabled for balanced mode --- VoidLink/Stream/VideoDecoderRenderer.h | 1 + VoidLink/Stream/VideoDecoderRenderer.m | 9 +++++++-- VoidLink/ViewControllers/StreamFrameViewController.m | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/VoidLink/Stream/VideoDecoderRenderer.h b/VoidLink/Stream/VideoDecoderRenderer.h index 3bc61d06..be311fd1 100644 --- a/VoidLink/Stream/VideoDecoderRenderer.h +++ b/VoidLink/Stream/VideoDecoderRenderer.h @@ -18,6 +18,7 @@ @property (atomic, readonly) PlotMetrics decodeMetrics; @property (atomic, readonly) PlotMetrics frameQueueMetrics; +@property (atomic, assign) bool appDidEnterBackgroundWithoutPiP; @property (nonatomic, strong, readonly) AVSampleBufferDisplayLayer *displayLayer; diff --git a/VoidLink/Stream/VideoDecoderRenderer.m b/VoidLink/Stream/VideoDecoderRenderer.m index 0609eaa1..fa655275 100644 --- a/VoidLink/Stream/VideoDecoderRenderer.m +++ b/VoidLink/Stream/VideoDecoderRenderer.m @@ -114,7 +114,9 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, { NSLog(@"initializing video decoder %f", CACurrentMediaTime()); self = [super init]; - + + _appDidEnterBackgroundWithoutPiP = false; + _sq = dispatch_queue_create("com.moonlight.VideoDecoderRenderer", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0)); @@ -263,6 +265,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); // DisplayLink calls us every vsync we we try to present the most recent frame. We try to maintain a user-configurable buffer // of 1-5 frames. If the buffer is full, every other frame is dropped which just appears to the user as a lower framerate stream. - (void)renderModeAVSB:(CADisplayLink *)link { + CFTimeInterval start = link.timestamp; CFTimeInterval deadline = link.targetTimestamp; static CFTimeInterval lastTargetLocal = 0.0f; @@ -326,6 +329,8 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); // Legacy frame pacing callback - matches upstream/Integration behavior exactly - (void)displayLinkCallback:(CADisplayLink *)sender { + if(_appDidEnterBackgroundWithoutPiP) return; + VIDEO_FRAME_HANDLE handle; PDECODE_UNIT du; @@ -374,7 +379,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); Log(LOG_I, @"Setting timebase for stream to %d / %d", pts.value, pts.timescale); } - [self->_displayLayer enqueueSampleBuffer:frame.sampleBuffer]; + if(!_appDidEnterBackgroundWithoutPiP) [self->_displayLayer enqueueSampleBuffer:frame.sampleBuffer]; #ifdef DISPLAYLINK_VERBOSE // Some OS-level metrics I'm not sure what to do with diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 82c9ac15..5c24d22a 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -1031,6 +1031,8 @@ - (void)applicationWillResignActive:(NSNotification *)notification { //[self.pipController startPictureInPicture]; //sleep(1); + _streamMan.videoRenderer.appDidEnterBackgroundWithoutPiP = true; + [_streamView saveRelocatedWidgetViews]; #if !TARGET_OS_TV @@ -1046,6 +1048,7 @@ } - (void)applicationDidBecomeActive:(NSNotification *)notification { + _streamMan.videoRenderer.appDidEnterBackgroundWithoutPiP = false; // Stop the background timer, since we're foregrounded again if (_inactivityTimer != nil) { Log(LOG_I, @"Stopping inactivity timer after becoming active again"); @@ -1075,11 +1078,13 @@ // This fires when the home button is pressed - (void)applicationDidEnterBackground:(UIApplication *)application { - NSLog(@"did enter background, %d, %@, %d", _settings.enablePIP, self.pipController, self.pipController.isPictureInPictureActive); if (_settings.enablePIP && self.pipController && self.pipController.isPictureInPictureActive) { //Log(LOG_I, @"PIP is active, not terminating stream"); + _streamMan.videoRenderer.appDidEnterBackgroundWithoutPiP = false; } else { + _streamMan.videoRenderer.appDidEnterBackgroundWithoutPiP = true; + if ([_settings.renderingBackend intValue] == RENDER_METAL && self.metalViewController) { Log(LOG_I, @"Pausing Metal renderer on background"); [self.metalViewController pauseRendering];