fix(macos): reduce idle CPU when video player is paused
- Remove vulkan-swap-mode mailbox (continuous GPU rendering even when paused) - End playback activity assertion on pause, restore on play - Fix PerformanceStatsService persistent frame callback leak
This commit is contained in:
+10
-1
@@ -33,6 +33,8 @@ class PerformanceStatsService {
|
||||
int _frameCount = 0;
|
||||
DateTime _lastFpsUpdate = DateTime.now();
|
||||
double? _currentUiFps;
|
||||
bool _fpsTrackingActive = false;
|
||||
bool _fpsCallbackRegistered = false;
|
||||
|
||||
// Track runtime player type for logging (can differ from Dart object type after fallback)
|
||||
// Values: 'exoplayer', 'mpv', or 'unknown'
|
||||
@@ -77,11 +79,16 @@ class PerformanceStatsService {
|
||||
void _startFpsTracking() {
|
||||
_frameCount = 0;
|
||||
_lastFpsUpdate = DateTime.now();
|
||||
SchedulerBinding.instance.addPersistentFrameCallback(_onFrame);
|
||||
_fpsTrackingActive = true;
|
||||
if (!_fpsCallbackRegistered) {
|
||||
_fpsCallbackRegistered = true;
|
||||
SchedulerBinding.instance.addPersistentFrameCallback(_onFrame);
|
||||
}
|
||||
}
|
||||
|
||||
/// Called every frame to count FPS.
|
||||
void _onFrame(Duration timestamp) {
|
||||
if (!_fpsTrackingActive) return;
|
||||
_frameCount++;
|
||||
final now = DateTime.now();
|
||||
final elapsed = now.difference(_lastFpsUpdate);
|
||||
@@ -96,6 +103,8 @@ class PerformanceStatsService {
|
||||
void stopPolling() {
|
||||
_pollingTimer?.cancel();
|
||||
_pollingTimer = null;
|
||||
_fpsTrackingActive = false;
|
||||
_currentUiFps = null;
|
||||
}
|
||||
|
||||
/// Fetch all performance stats from the player.
|
||||
|
||||
@@ -85,7 +85,7 @@ class MpvPlayerCore: MpvPlayerCoreBase {
|
||||
override func configurePlatformMpvOptions() {
|
||||
guard let mpv else { return }
|
||||
checkError(mpv_set_option_string(mpv, "ao", "avfoundation,coreaudio"))
|
||||
checkError(mpv_set_option_string(mpv, "vulkan-swap-mode", "mailbox"))
|
||||
// Default fifo (vsync) mode — mailbox was causing continuous GPU rendering even when paused
|
||||
}
|
||||
|
||||
var videoLayer: CAMetalLayer? { metalLayer }
|
||||
@@ -113,9 +113,13 @@ class MpvPlayerCore: MpvPlayerCoreBase {
|
||||
command(["seek", "0", "relative+exact"])
|
||||
}
|
||||
|
||||
private var isVisible = false
|
||||
|
||||
func setVisible(_ visible: Bool) {
|
||||
guard let metalLayer, !isPipActive else { return }
|
||||
|
||||
isVisible = visible
|
||||
|
||||
if visible {
|
||||
metalLayer.removeFromSuperlayer()
|
||||
if let superlayer = window?.contentView?.layer {
|
||||
@@ -130,6 +134,14 @@ class MpvPlayerCore: MpvPlayerCoreBase {
|
||||
print("[MpvPlayerCore] setVisible(\(visible))")
|
||||
}
|
||||
|
||||
func setPaused(_ paused: Bool) {
|
||||
if paused {
|
||||
endPlaybackActivity()
|
||||
} else if isVisible {
|
||||
beginPlaybackActivity()
|
||||
}
|
||||
}
|
||||
|
||||
func updateFrame(_ frame: CGRect? = nil) {
|
||||
guard let metalLayer, !isPipActive else { return }
|
||||
|
||||
|
||||
@@ -277,6 +277,7 @@ class MpvPlayerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, MpvPluginS
|
||||
if name == "pause" {
|
||||
let isPlaying = value == "no"
|
||||
pipController?.setPlaying(isPlaying)
|
||||
playerCore?.setPaused(!isPlaying)
|
||||
}
|
||||
|
||||
result(nil)
|
||||
|
||||
Reference in New Issue
Block a user