From 96f79f7c72310870d91e5a93035701a07f758fc9 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sun, 2 Nov 2025 18:33:05 +0530 Subject: [PATCH] ksplayer optimizations --- ios/KSPlayerView.swift | 123 ++++++++++++++++-- ios/Nuvio.xcodeproj/project.pbxproj | 2 +- ios/Nuvio/Info.plist | 194 ++++++++++++++-------------- ios/Nuvio/NuvioRelease.entitlements | 9 +- 4 files changed, 211 insertions(+), 117 deletions(-) diff --git a/ios/KSPlayerView.swift b/ios/KSPlayerView.swift index 98b2986..19469e7 100644 --- a/ios/KSPlayerView.swift +++ b/ios/KSPlayerView.swift @@ -253,7 +253,14 @@ class KSPlayerView: UIView { KSOptions.hardwareDecode = false KSOptions.asynchronousDecompression = false KSOptions.secondPlayerType = nil + #else + // PERFORMANCE OPTIMIZATION: Enable asynchronous decompression globally + // This ensures the global default is correct for all player instances + KSOptions.asynchronousDecompression = true + // Ensure hardware decode is enabled globally + KSOptions.hardwareDecode = true #endif + print("KSPlayerView: [PERF] Global settings: asyncDecomp=\(KSOptions.asynchronousDecompression), hwDecode=\(KSOptions.hardwareDecode)") } private func updateSubtitleFont(size: CGFloat) { @@ -343,15 +350,45 @@ class KSPlayerView: UIView { } private func createOptions(with headers: [String: String]) -> KSOptions { - let options = KSOptions() + // Use custom HighPerformanceOptions subclass for frame buffer optimization + let options = HighPerformanceOptions() // Disable native player remote control center integration; use RN controls options.registerRemoteControll = false - // Reduce prebuffer to speed up start/seeks; keep a modest upper cap - options.preferredForwardBufferDuration = 0.5 - options.maxBufferDuration = 10.0 - // Enable "second open" to relax startup/seek buffering thresholds + + // PERFORMANCE OPTIMIZATION: Optimal buffer durations for high bitrate + // Increased buffer prevents stuttering during network hiccups with high bitrate streams + options.preferredForwardBufferDuration = 3.0 // Increased from 0.5 for high bitrate stability + options.maxBufferDuration = 20.0 // Increased from 10.0 to allow more aggressive buffering + + // Enable "second open" to relax startup/seek buffering thresholds (already enabled) options.isSecondOpen = true + // PERFORMANCE OPTIMIZATION: Fast stream analysis for high bitrate content + // Reduces startup latency significantly for large high-bitrate streams + options.probesize = 50_000_000 // 50MB for faster format detection + options.maxAnalyzeDuration = 5_000_000 // 5 seconds in microseconds for faster stream structure analysis + + // PERFORMANCE OPTIMIZATION: Decoder thread optimization + // Use all available CPU cores for parallel decoding + options.decoderOptions["threads"] = "0" // Use all CPU cores instead of "auto" + // refcounted_frames already set to "1" in KSOptions init for memory efficiency + + // PERFORMANCE OPTIMIZATION: Hardware decode explicitly enabled + // Ensure VideoToolbox hardware acceleration is always preferred for non-simulator + #if targetEnvironment(simulator) + options.hardwareDecode = false + options.asynchronousDecompression = false + #else + options.hardwareDecode = true // Explicitly enable hardware decode + // PERFORMANCE OPTIMIZATION: Asynchronous decompression (CRITICAL) + // Offloads VideoToolbox decompression to background threads, preventing main thread stalls + options.asynchronousDecompression = true + #endif + + // PERFORMANCE OPTIMIZATION: Native HDR processing + // Set destination dynamic range based on device capabilities to eliminate unnecessary color conversions + options.destinationDynamicRange = getOptimalDynamicRange() + // Configure audio for proper dialogue mixing using FFmpeg's pan filter // This approach uses standard audio engineering practices for multi-channel downmixing @@ -365,12 +402,6 @@ class KSPlayerView: UIView { // This provides better spatial audio processing and natural dialogue mixing // options.audioFilters.append("surround=ang=45") - #if targetEnvironment(simulator) - options.hardwareDecode = false - options.asynchronousDecompression = false - #else - options.hardwareDecode = KSOptions.hardwareDecode - #endif if !headers.isEmpty { // Clean and validate headers before adding var cleanHeaders: [String: String] = [:] @@ -391,6 +422,9 @@ class KSPlayerView: UIView { } } } + + print("KSPlayerView: [PERF] High-performance options configured: asyncDecomp=\(options.asynchronousDecompression), hwDecode=\(options.hardwareDecode), buffer=\(options.preferredForwardBufferDuration)s/\(options.maxBufferDuration)s, HDR=\(options.destinationDynamicRange?.description ?? "auto")") + return options } @@ -768,6 +802,73 @@ class KSPlayerView: UIView { "volume": currentVolume ] } + + // MARK: - Performance Optimization Helpers + + /// Detects device HDR capabilities and returns optimal dynamic range setting + /// This prevents unnecessary color space conversion overhead + private func getOptimalDynamicRange() -> DynamicRange? { + #if canImport(UIKit) + let availableHDRModes = AVPlayer.availableHDRModes + + // If no HDR modes available, use SDR (nil will use content's native range) + if availableHDRModes == AVPlayer.HDRMode(rawValue: 0) { + return .sdr + } + + // Prefer HDR10 if supported (most common HDR format) + if availableHDRModes.contains(.hdr10) { + return .hdr10 + } + + // Fallback to Dolby Vision if available + if availableHDRModes.contains(.dolbyVision) { + return .dolbyVision + } + + // Fallback to HLG if available + if availableHDRModes.contains(.hlg) { + return .hlg + } + + // Default to SDR if no HDR support + return .sdr + #else + // macOS: Check screen capabilities + return .sdr + #endif + } +} + +// MARK: - High Performance KSOptions Subclass + +/// Custom KSOptions subclass that overrides frame buffer capacity for high bitrate content +/// More buffered frames absorb decode spikes and network hiccups without quality loss +private class HighPerformanceOptions: KSOptions { + /// Override to increase frame buffer capacity for high bitrate content + /// - Parameters: + /// - fps: Video frame rate + /// - naturalSize: Video resolution + /// - isLive: Whether this is a live stream + /// - Returns: Number of frames to buffer + override func videoFrameMaxCount(fps: Float, naturalSize: CGSize, isLive: Bool) -> UInt8 { + if isLive { + // Increased from 4 to 8 for better live stream stability + return 8 + } + + // For high bitrate VOD: increase buffer based on resolution + if naturalSize.width >= 3840 || naturalSize.height >= 2160 { + // 4K needs more buffer frames to handle decode spikes + return 32 + } else if naturalSize.width >= 1920 || naturalSize.height >= 1080 { + // 1080p benefits from more frames + return 24 + } + + // Default for lower resolutions + return 16 + } } extension KSPlayerView: KSPlayerLayerDelegate { diff --git a/ios/Nuvio.xcodeproj/project.pbxproj b/ios/Nuvio.xcodeproj/project.pbxproj index 3acee97..678af2b 100644 --- a/ios/Nuvio.xcodeproj/project.pbxproj +++ b/ios/Nuvio.xcodeproj/project.pbxproj @@ -490,7 +490,7 @@ "-lc++", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; - PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app; + PRODUCT_BUNDLE_IDENTIFIER = com.nuviohub.app; PRODUCT_NAME = Nuvio; SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/ios/Nuvio/Info.plist b/ios/Nuvio/Info.plist index 2e04327..3336aee 100644 --- a/ios/Nuvio/Info.plist +++ b/ios/Nuvio/Info.plist @@ -1,101 +1,99 @@ - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Nuvio - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.2.7 - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - nuvio - com.nuvio.app - - - - CFBundleURLSchemes - - exp+nuvio - - - - CFBundleVersion - 22 - LSMinimumSystemVersion - 12.0 - LSRequiresIPhoneOS - - LSSupportsOpeningDocumentsInPlace - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - NSBonjourServices - - _http._tcp - - NSLocalNetworkUsageDescription - Allow $(PRODUCT_NAME) to access your local network - NSMicrophoneUsageDescription - This app does not require microphone access. - RCTNewArchEnabled - - RCTRootViewBackgroundColor - 4278322180 - UIBackgroundModes - - audio - - UIFileSharingEnabled - - UILaunchStoryboardName - SplashScreen - UIRequiredDeviceCapabilities - - arm64 - - UIRequiresFullScreen - - UIStatusBarStyle - UIStatusBarStyleDefault - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIUserInterfaceStyle - Dark - UIViewControllerBasedStatusBarAppearance - - - \ No newline at end of file + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Nuvio + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.2.7 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + nuvio + com.nuvio.app + + + + CFBundleURLSchemes + + exp+nuvio + + + + CFBundleVersion + 22 + LSMinimumSystemVersion + 12.0 + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSBonjourServices + + _http._tcp + + NSLocalNetworkUsageDescription + Allow $(PRODUCT_NAME) to access your local network + RCTNewArchEnabled + + RCTRootViewBackgroundColor + 4278322180 + UIBackgroundModes + + audio + + UIFileSharingEnabled + + UILaunchStoryboardName + SplashScreen + UIRequiredDeviceCapabilities + + arm64 + + UIRequiresFullScreen + + UIStatusBarStyle + UIStatusBarStyleDefault + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIUserInterfaceStyle + Dark + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Nuvio/NuvioRelease.entitlements b/ios/Nuvio/NuvioRelease.entitlements index a0bc443..0c67376 100644 --- a/ios/Nuvio/NuvioRelease.entitlements +++ b/ios/Nuvio/NuvioRelease.entitlements @@ -1,10 +1,5 @@ - - aps-environment - development - com.apple.developer.associated-domains - - - \ No newline at end of file + +